文章目录
- 题目描述
- 解析
- 代码
题目描述
Alice 和 Bob 居住在一个由 NN 座岛屿组成的国家,岛屿被编号为 00 到 N-1N−1。某些岛屿之间有桥相连,桥上的道路是双向的,但一次只能供一人通行。其中一些桥由于年久失修成为危桥,最多只能通行两次。
Alice 希望在岛屿 a1和 a2 之间往返 an次(从 a1 到 a2再从 a2 到 a1 算一次往返)。同时,Bob 希望在岛屿 b1和 b2之间往返 bn次。这个过程中,所有危桥最多通行两次,其余的桥可以无限次通行。请问 Alice 和 Bob 能完成他们的愿望吗?
解析
首先可以把往返看成单程,危桥当成只能通过1次
建图方法和显然,但是会忽略a1流向b2、b1流向a2的问题
一个很巧妙的解决办法是交换b1和b2,再跑一次,如果还是满流,就是合法的
代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=2600;
const int M=1e9;
ll read(){ll x=0,f=1;char c=getchar();while(!isdigit(c)){if(c=='-') f=-1;c=getchar();};while(isdigit(c)){x=x*10+c-'0';c=getchar();}return x*f;
}
int n,m,s,t;
struct node{int to,nxt;ll cap;
}p[N*N*2];
int fi[N],cnt;
void addline(int x,int y,ll cap){
// printf("x=%d y=%d cap=%lld\n",x,y,cap);p[++cnt]=(node){y,fi[x],cap};fi[x]=cnt;p[++cnt]=(node){x,fi[y],0};fi[y]=cnt;
}
int bel[N],cur[N];
queue<int>q;
int bfs(){memset(bel,0,sizeof(bel));bel[s]=1;q.push(s);while(!q.empty()){int now=q.front();q.pop();//printf("now=%d\n",now);for(int i=cur[now]=fi[now];~i;i=p[i].nxt){int to=p[i].to;//printf(" to=%d\n",to);if(bel[to]||!p[i].cap) continue;//printf(" ok\n");bel[to]=bel[now]+1;q.push(to);}}return bel[t];
}
ll dfs(int x,ll lim){if(x==t||!lim) return lim;ll res=0;for(int &i=cur[x];~i&&lim;i=p[i].nxt){int to=p[i].to;if(!p[i].cap||bel[to]!=bel[x]+1) continue;ll add=dfs(to,min(lim,p[i].cap));res+=add;lim-=add;p[i].cap-=add;p[i^1].cap+=add;if(!lim) break;}if(!res) bel[x]=-1;return res;
}
ll dinic(){ll tot=0;while(bfs()){//printf("ok");while(ll tmp=dfs(s,2e15)) tot+=tmp;}
// printf("tot=%lld\n",tot);return tot;
}
int a1,a2,an,b1,b2,bn;
char ss[60][60];
void build(){char c;memset(fi,-1,sizeof(fi));cnt=-1;for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){c=ss[i][j];if(c=='X') continue;else if(c=='N') addline(i,j,2e18);else addline(i,j,1);}}
}
int main(){while(scanf("%d%d%d%d%d%d%d",&n,&a1,&a2,&an,&b1,&b2,&bn)!=EOF){a1++;a2++;b1++;b2++;for(int i=1;i<=n;i++){scanf(" %s",ss[i]+1);}s=n+1;t=n+2;build();addline(s,a1,an);addline(a2,t,an);addline(s,b1,bn);addline(b2,t,bn);if(dinic()!=an+bn){printf("No\n");continue;}build();addline(s,a1,an);addline(a2,t,an);addline(s,b2,bn);addline(b1,t,bn);if(dinic()!=an+bn) printf("No\n");else printf("Yes\n");}return 0;
}
/**/