「BZOJ3504」[CQOI2014] 危桥
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”表示没有桥相连。
|
每组数据第一行包含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
题解
网络流即可。。。但是只做一遍会有问题:比如从a1万一到不了a2,然而最终流到了b2,这样显然是不可行的。那么我们可以把b1和b2反一下再做一遍,如果还是满流就可以了。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | #include<iostream> #include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring> #define inf 0x7fffffff #define ll long long #define T 51 using namespace std; bool flag; int n,a1,a2,an,b1,b2,bn; int cnt,ans; int h[55],q[55]; int mp[55][55]; struct data{int to,next,v;}e[100005];int head[55],cur[55]; void ins(int u,int v,int w) {e[++cnt].to=v;e[cnt].next=head[u];head[u]=cnt;e[cnt].v=w;} void insert(int u,int v,int w) {ins(u,v,w);ins(v,u,0);} void build() { 	memset(head,0,sizeof(head));cnt=1; 	for(int i=1;i<=n;i++) 	    for(int j=1;j<=n;j++) 	        if(mp[i][j]==1)insert(i,j,2); 	        else if(mp[i][j]==2)insert(i,j,inf); } bool bfs() {     int t=0,w=1;     for(int i=0;i<=T;i++)h[i]=-1;     q[0]=0;h[0]=0;     while(t!=w)     {         int now=q[t];t++;         for(int i=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)return 0;     return 1; } int dfs(int x,int f) {     if(x==T)return f;     int w,used=0;     for(int i=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)return f;         }     }     if(!used)h[x]=-1;     return used; } void dinic() {while(bfs()){for(int i=0;i<=T;i++)cur[i]=head[i];ans+=dfs(0,inf);}} int main() { 	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(int i=1;i<=n;i++) 		{ 			char ch[55]; 			scanf("%s",ch); 			for(int j=1;j<=n;j++) 			    if(ch[j-1]=='O')mp[i][j]=1; 			    else if(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"); 		else printf("Yes\n"); 	} 	return 0; } | 
 
			
黄学长……请问这么建边为何不会出现对于x-y的危桥,x->y先走了2次,然后y->x又走了4次,这样重复下去?
其实你多建立一倍的边