bzoj3504[Cqoi2014]危桥
题意:
有N座岛屿,某些岛屿之间有桥相连,桥上的道路是双向的,但一次只能供一人通行。其中一些桥是危桥。Alice希望在岛屿al和a2之间往返an次(从al到a2再从a2 到al算一次往返)。同时,Bob希望在岛屿bl和b2之间往返bn次。这个过程中,所有危桥最多通行两次,其余的桥可以无限次通行。判断两人能否达成愿望。
题解:
网络流,每天边的容量就是这条边可以走几次,建一个超级源连a1b1,a2b2连超级汇,如果最大流大于等于2*(b1+b2)就行。但有可能出现a1流到b2导致原来的不可行被判断成可行,这样我们就需要把b2和b1调换位置,如果结果一样,说明这个方案是真正可行的,具体原因我还不懂,好像是如果两个结果一样,即使真的出现了a1流到b2的情况,也能通过调整变成正确的流动方案,蒟蒻太弱了!
代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <queue> 5 #define INF 0x3fffffff 6 #define inc(i,j,k) for(int i=j;i<=k;i++) 7 using namespace std; 8 9 struct e{int t,c,n;}; e es[10000]; int ess,g[100]; 10 void pe(int f,int t,int c){es[++ess]=(e){t,c,g[f]}; g[f]=ess; es[++ess]=(e){f,0,g[t]}; g[t]=ess;} 11 char map[100][100]; int n,a1,a2,an,b1,b2,bn,s,t; 12 queue <int> q; int h[100]; 13 bool bfs(int s,int t){ 14 while(! q.empty())q.pop(); memset(h,-1,sizeof(h)); h[s]=0; q.push(s); 15 while(! q.empty()){ 16 int x=q.front(); q.pop(); 17 for(int i=g[x];i!=-1;i=es[i].n)if(es[i].c&&h[es[i].t]==-1)h[es[i].t]=h[x]+1,q.push(es[i].t); 18 } 19 if(h[t]==-1)return 0;else return 1; 20 } 21 int dfs(int x,int t,int f){ 22 if(x==t)return f; int u=0; 23 for(int i=g[x];i!=-1;i=es[i].n)if(es[i].c&&h[es[i].t]==h[x]+1){ 24 int w=dfs(es[i].t,t,min(f,es[i].c)); es[i].c-=w; es[i^1].c+=w; f-=w; u+=w; 25 if(f==0)return u; 26 } 27 if(u==0)h[x]=-1; return u; 28 } 29 int dinic(int s,int t){int f=0; while(bfs(s,t))f+=dfs(s,t,INF); return f;} 30 int main(){ 31 while(scanf("%d%d%d%d%d%d%d",&n,&a1,&a2,&an,&b1,&b2,&bn)!=EOF){ 32 inc(i,1,n)scanf("%s",map[i]); a1++; a2++; b1++; b2++; s=0; t=n+1; 33 ess=-1; memset(g,-1,sizeof(g)); pe(s,a1,2*an); pe(s,b1,2*bn); pe(a2,t,2*an); pe(b2,t,2*bn); 34 inc(i,1,n)inc(j,0,n-1){ 35 if(map[i][j]=='O')pe(i,j+1,2); 36 if(map[i][j]=='N')pe(i,j+1,INF); 37 } 38 if(dinic(s,t)>=2*an+2*bn){ 39 ess=-1; memset(g,-1,sizeof(g)); pe(s,a1,2*an); pe(s,b2,2*bn); pe(a2,t,2*an); pe(b1,t,2*bn); 40 inc(i,1,n)inc(j,0,n-1){ 41 if(map[i][j]=='O')pe(i,j+1,2); 42 if(map[i][j]=='N')pe(i,j+1,INF); 43 } 44 if(dinic(s,t)>=2*an+2*bn)printf("Yes\n");else printf("No\n"); 45 }else printf("No\n"); 46 } 47 return 0; 48 }
20160408