Alice和Bob居住在一个由N座岛屿组成的国家,岛屿被编号为0到N-1。某些岛屿之间有桥相连,桥上的道路是双
向的,但一次只能供一人通行。其中一些桥由于年久失修成为危桥,最多只能通行两次。Alice希望在岛屿al和a2之间往返an次(从al到a2再从a2到al算一次往返)。同时,Bob希望在岛屿bl和b2之间往返bn次。这个过程中,所有危桥最多通行两次,其余的桥可以无限次通行。请问Alice和Bob能完成他们的愿望吗?
Alice和Bob居住在一个由N座岛屿组成的国家,岛屿被编号为0到N-1。某些岛屿之间有桥相连,桥上的道路是双
向的,但一次只能供一人通行。其中一些桥由于年久失修成为危桥,最多只能通行两次。Alice希望在岛屿al和a2之间往返an次(从al到a2再从a2到al算一次往返)。同时,Bob希望在岛屿bl和b2之间往返bn次。这个过程中,所有危桥最多通行两次,其余的桥可以无限次通行。请问Alice和Bob能完成他们的愿望吗?
本题有多组测试数据。
每组数据第一行包含7个空格隔开的整数,分别为N、al、a2、an、bl、b2、bn。
接下来是一个N行N列的对称矩阵,由大写字母组成。矩阵的i行j列描述编号i一1和j-l的岛屿间的连接情况,若为“O”则表示有危桥相连:为“N”表示有普通的桥相连:为“X”表示没有桥相连。
|
对于每组测试数据输出一行,如果他们都能完成愿望输出“Yes”,否则输出“No”。
做了很多网络流,可是考试时还是想不出如何构图,就好像听了无数人生大道理,却依旧过不好这一生。
如果是危桥则连容量为2的双向边,否则就连容量为正无穷的双向边,然后s到a1和b1分别连容量为2*an和2*bn的边,a2和b2到t分别容量为2*an和2*bn的边。跑最大流,判断是否等于2*(an+bn)。
但是这样做有一点问题,就是a1可能会流到b2,b1可能会流到a2,这显然是错误的。
考虑再构建一次图:交换b1和b2,即s到a1和b2分别连容量为2*an和2*bn的边,a2和b1到t分别容量为2*an和2*bn的边。再跑一次最大流,判断是否等于2*(an+bn)。这样就解决了刚才的问题。
证明:http://www.cnblogs.com/zyfzyf/p/4193441.html
#include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #include<cstring> #include<algorithm> #include<queue> #define F(i,j,n) for(int i=j;i<=n;i++) #define D(i,j,n) for(int i=j;i>=n;i--) #define ll long long #define maxn 100 #define maxm 3000 #define inf 1000000000 using namespace std; int n,a1,a2,an,b1,b2,bn,s,t,cnt,ans; int head[maxn],cur[maxn],dis[maxn]; char ch[maxn][maxn]; struct edge_type{int next,to,v;}e[maxm]; inline void add_edge(int x,int y,int v1,int v2) { e[++cnt]=(edge_type){head[x],y,v1};head[x]=cnt; e[++cnt]=(edge_type){head[y],x,v2};head[y]=cnt; } inline void build() { memset(head,0,sizeof(head)); cnt=1; F(i,1,n-1) { F(j,i+1,n) { if (ch[i][j]=='O') add_edge(i,j,2,2); else if (ch[i][j]=='N') add_edge(i,j,inf,inf); } } } inline bool bfs() { queue<int> q; memset(dis,-1,sizeof(dis)); dis[s]=0;q.push(s); while (!q.empty()) { int x=q.front();q.pop(); if (x==t) return true; for(int i=head[x];i;i=e[i].next) { int y=e[i].to; if (e[i].v&&dis[y]==-1) { dis[y]=dis[x]+1; q.push(y); } } } return false; } inline int dfs(int x,int f) { int tmp,sum=0; if (x==t) return f; for(int &i=cur[x];i;i=e[i].next) { int y=e[i].to; if (e[i].v&&dis[y]==dis[x]+1) { tmp=dfs(y,min(e[i].v,f-sum)); sum+=tmp;e[i].v-=tmp;e[i^1].v+=tmp; if (f==sum) return sum; } } if (!sum) dis[x]=-1; return sum; } inline void dinic() { ans=0; while (bfs()) { F(i,1,t) cur[i]=head[i]; ans+=dfs(s,inf); } } int main() { while (scanf("%d%d%d%d%d%d%d",&n,&a1,&a2,&an,&b1,&b2,&bn)!=EOF) { a1++;a2++;b1++;b2++;an*=2;bn*=2; F(i,1,n) scanf("%s",ch[i]+1); s=n+1;t=n+2; build(); add_edge(s,a1,an,0);add_edge(a2,t,an,0); add_edge(s,b1,bn,0);add_edge(b2,t,bn,0); dinic(); if (ans!=an+bn){puts("No");continue;} build(); add_edge(s,a1,an,0);add_edge(a2,t,an,0); add_edge(s,b2,bn,0);add_edge(b1,t,bn,0); dinic(); if (ans!=an+bn){puts("No");continue;} puts("Yes"); } }