您的位置:首页 > 理论基础 > 计算机网络

bzoj 3504(神题,网络流)

2016-04-12 09:51 344 查看

3504: [Cqoi2014]危桥

Time Limit: 10 Sec Memory Limit: 128 MB

Submit: 1165 Solved: 590

[Submit][Status][Discuss]

Description

Alice和Bob居住在一个由N座岛屿组成的国家,岛屿被编号为0到N-1。某些岛屿之间有桥相连,桥上的道路是双

向的,但一次只能供一人通行。其中一些桥由于年久失修成为危桥,最多只能通行两次。Alice希望在岛屿al和a2之间往返an次(从al到a2再从a2到al算一次往返)。同时,Bob希望在岛屿bl和b2之间往返bn次。这个过程中,所有危桥最多通行两次,其余的桥可以无限次通行。请问Alice和Bob能完成他们的愿望吗?

Input

本题有多组测试数据。

每组数据第一行包含7个空格隔开的整数,分别为N、al、a2、an、bl、b2、bn。

接下来是一个N行N列的对称矩阵,由大写字母组成。矩阵的i行j列描述编号i一1和j-l的岛屿间的连接情况,若为“O”则表示有危桥相连:为“N”表示有普通的桥相连:为“X”表示没有桥相连。

|

Output

对于每组测试数据输出一行,如果他们都能完成愿望输出“Yes”,否则输出“No”。

Sample Input

4 0 1 1 2 3 1

XOXX

OXOX

XOXO

XXOX

4 0 2 1 1 3 2

XNXO

NXOX

XOXO

OXOX

Sample Output

Yes

No

数据范围

4<=N<50

O<=a1, a2, b1, b2<=N-1

1 <=an. b<=50

解题思路:

神题。。。 网上证明好像有问题。。

就是先建图,跑最大流,看ans是否是2*an+2*bn。

满足的话,将b1,b2交换再做,再判断,如果还满足就满足。

以后遇到这种题的话,实在不会证,就看看是否是满足对称性的,再考虑交换来做。

#include<iostream>

#include<cstdio>

#include<cstdlib>

#include<algorithm>

#include<cstring>

#define inf 0x7fffffff

#define ll long long

#define T 51

usingnamespacestd;

boolflag;

intn,a1,a2,an,b1,b2,bn;

intcnt,ans;

inth[55],q[55];

intmp[55][55];

structdata{intto,next,v;}e[100005];inthead[55],cur[55];

voidins(intu,intv,intw)

{e[++cnt].to=v;e[cnt].next=head[u];head[u]=cnt;e[cnt].v=w;}

voidinsert(intu,intv,intw)

{ins(u,v,w);ins(v,u,0);}

voidbuild()

{

memset(head,0,sizeof(head));cnt=1;

for(inti=1;i<=n;i++)

for(intj=1;j<=n;j++)

if(mp[i][j]==1)insert(i,j,2);

elseif(mp[i][j]==2)insert(i,j,inf);

}

boolbfs()

{

intt=0,w=1;

for(inti=0;i<=T;i++)h[i]=-1;

q[0]=0;h[0]=0;

while(t!=w)

{

intnow=q[t];t++;

for(inti=head[now];i;i=e[i].next)

if(e[i].v&&h[e[i].to]==-1)

{

h[e[i].to]=h[now]+1;

q[w++]=e[i].to;

}

}

if(h[T]==-1)return0;

return1;

}

intdfs(intx,intf)

{

if(x==T)returnf;

intw,used=0;

for(inti=cur[x];i;i=e[i].next)

{

if(e[i].v&&h[e[i].to]==h[x]+1)

{

w=f-used;

w=dfs(e[i].to,min(e[i].v,w));

e[i].v-=w;

if(e[i].v)cur[x]=i;

e[i^1].v+=w;

used+=w;if(used==f)returnf;

}

}

if(!used)h[x]=-1;

returnused;

}

voiddinic()

{while(bfs()){for(inti=0;i<=T;i++)cur[i]=head[i];ans+=dfs(0,inf);}}

intmain()

{

while(scanf("%d%d%d%d%d%d%d",&n,&a1,&a2,&an,&b1,&b2,&bn)!=EOF)

{

memset(mp,0,sizeof(mp));flag=0;

a1++;a2++;b1++;b2++;

for(inti=1;i<=n;i++)

{

charch[55];

scanf("%s",ch);

for(intj=1;j<=n;j++)

if(ch[j-1]=='O')mp[i][j]=1;

elseif(ch[j-1]=='N')mp[i][j]=2;

}

build();

insert(0,a1,an*2);insert(a2,T,an*2);

insert(0,b1,bn*2);insert(b2,T,bn*2);

ans=0;

dinic();

if(ans<2*(an+bn))flag=1;

if(!flag)

{

build();

insert(0,a1,an*2);insert(a2,T,an*2);

insert(0,b2,bn*2);insert(b1,T,bn*2);

ans=0;

dinic();

if(ans<2*(an+bn))flag=1;

}

if(flag)printf("No\n");

elseprintf("Yes\n");

}

return0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: