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
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
No
数据范围
4<=N<50
O<=a1, a2, b1, b2<=N-1
1 <=an. b<=50
题解:
这道题有个看上去正确的方法,就是将原图的边保留,容量为它原来能走的次数,从S向a1,b1分别连容量为an*2,bn*2的边,从a2,b2分别向T连容量为an*2,bn*2的边,然后如果最大流=an*2+bn*2,则可行
这个方法是错误的
如图,a1有流向b2的边,b1有流向a2的边,如果这个图满足上面的条件,但它不一定可行
如何能保证可行?我们只需要将b1和b2交换一下再判一遍即可
假如一个a1到b2的一个流和b1到a2的一个流分别经过了一个桥的两个端点(u,v),如图
我们就可以将a1到b2的流量改为经过u-v-a2-T到达T,同理将b1到a2的流量改为经过v-u-b2-T到达T,这样就说明这个流是没有问题的
在这种情况下将b1和b2交换后,流量显然不会有变化
如果一个a1到b2的一个流和b1到a2的一个流没有经过任何一个桥的两个端点,这个流显然不合法,且在b1和b2交换后,流量会减小
所以判两次就行了
code:
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 #define maxn 55 7 #define maxm 5050 8 #define inf 1061109567 9 using namespace std; 10 char s[52]; 11 int n,a1,a2,an,b1,b2,bn; 12 struct flow{ 13 int s,t,tot,now[maxn],son[maxm],pre[maxm],val[maxm]; 14 int dis[maxn],head,tail,list[maxn]; 15 bool bo[maxn]; 16 void init(){s=0,t=n+1,tot=1,memset(now,0,sizeof(now));} 17 void put(int a,int b,int c){pre[++tot]=now[a],now[a]=tot,son[tot]=b,val[tot]=c;} 18 void add(int a,int b,int c){put(a,b,c),put(b,a,0);} 19 bool bfs(){ 20 memset(bo,0,sizeof(bo)); 21 head=0,tail=1,list[1]=s,dis[s]=0,bo[s]=1; 22 while (head<tail){ 23 int u=list[++head]; 24 for (int p=now[u],v=son[p];p;p=pre[p],v=son[p]) 25 if (val[p]&&!bo[v]) bo[v]=1,dis[v]=dis[u]+1,list[++tail]=v; 26 } 27 return bo[t]; 28 } 29 int dfs(int u,int rest){ 30 if (u==t) return rest; 31 int ans=0; 32 for (int p=now[u],v=son[p];p&&rest;p=pre[p],v=son[p]) 33 if (val[p]&&dis[v]==dis[u]+1){ 34 int d=dfs(v,min(rest,val[p])); 35 val[p]-=d,val[p^1]+=d,ans+=d,rest-=d; 36 } 37 if (!ans) dis[u]=-1; 38 return ans; 39 } 40 int dinic(){ 41 int ans=0; 42 while (bfs()) ans+=dfs(s,inf); 43 return ans; 44 } 45 }f,g; 46 int main(){ 47 while (~scanf("%d%d%d%d%d%d%d",&n,&a1,&a2,&an,&b1,&b2,&bn)){ 48 a1++,a2++,an<<=1,b1++,b2++,bn<<=1,f.init(); 49 for (int i=1;i<=n;i++){ 50 scanf("%s",s+1); 51 for (int j=1;j<=n;j++) if (s[j]=='O') f.add(i,j,2); else if (s[j]=='N') f.add(i,j,inf); 52 } 53 g=f; 54 f.add(f.s,a1,an),f.add(a2,f.t,an),f.add(f.s,b1,bn),f.add(b2,f.t,bn); 55 g.add(g.s,a1,an),g.add(a2,g.t,an),g.add(g.s,b2,bn),g.add(b1,g.t,bn); 56 if (f.dinic()==an+bn&&g.dinic()==an+bn) puts("Yes"); else puts("No"); 57 } 58 return 0; 59 }