如果只有一个人的话很容易想到最大流,正常桥连限流inf双向边,危桥连限流2双向边即可。现在有两个人,容易想到给两起点建超源两汇点建超汇,但这样没法保证两个人各自到达自己要去的目的地。于是再超源连一个人的起点和另一个人的终点跑一遍,两次都满流说明有解。证明脑(bu)补(hui)。
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } #define N 55 #define S 0 #define T 51 int n,s1,t1,c1,s2,t2,c2,p[N],tmpp[N],t,tmpt,ans; int d[N],cur[N],q[N]; struct data{int to,nxt,cap,flow; }edge[N*N<<2],tmpedge[N*N<<2]; void addedge(int x,int y,int z) { t++;edge[t].to=y,edge[t].nxt=p[x],edge[t].cap=z,edge[t].flow=0,p[x]=t; t++;edge[t].to=x,edge[t].nxt=p[y],edge[t].cap=0,edge[t].flow=0,p[y]=t; } bool bfs() { memset(d,255,sizeof(d));d[S]=0; int head=0,tail=1;q[1]=S; do { int x=q[++head]; for (int i=p[x];~i;i=edge[i].nxt) if (d[edge[i].to]==-1&&edge[i].flow<edge[i].cap) { d[edge[i].to]=d[x]+1; q[++tail]=edge[i].to; } }while (head<tail); return ~d[T]; } int work(int k,int f) { if (k==T) return f; int used=0; for (int i=cur[k];~i;i=edge[i].nxt) if (d[k]+1==d[edge[i].to]) { int w=work(edge[i].to,min(f-used,edge[i].cap-edge[i].flow)); edge[i].flow+=w,edge[i^1].flow-=w; if (edge[i].flow<edge[i].cap) cur[k]=i; used+=w;if (used==f) return f; } if (used==0) d[k]=-1; return used; } void dinic() { while (bfs()) { memcpy(cur,p,sizeof(p)); ans+=work(S,N<<2); } } int main() { #ifndef ONLINE_JUDGE freopen("bzoj3504.in","r",stdin); freopen("bzoj3504.out","w",stdout); const char LL[]="%I64d\n"; #else const char LL[]="%lld\n"; #endif while (scanf("%d%d%d%d%d%d%d",&n,&s1,&t1,&c1,&s2,&t2,&c2)>0) { s1++,t1++,s2++,t2++;c1<<=1,c2<<=1; memset(p,255,sizeof(p));t=-1; for (int i=1;i<=n;i++) { char c; for (int j=1;j<=n;j++) { c=getchar(); while (c<'A'||c>'Z') c=getchar(); if (c=='O') addedge(i,j,2); else if (c=='N') addedge(i,j,N<<2); } } memcpy(tmpp,p,sizeof(p)); memcpy(tmpedge,edge,sizeof(edge)); tmpt=t; addedge(S,s1,c1); addedge(S,s2,c2); addedge(t1,T,c1); addedge(t2,T,c2); ans=0; dinic(); if (ans<c1+c2) cout<<"No\n"; else { memcpy(p,tmpp,sizeof(p)); memcpy(edge,tmpedge,sizeof(edge)); t=tmpt; addedge(S,s1,c1); addedge(S,t2,c2); addedge(t1,T,c1); addedge(s2,T,c2); ans=0; dinic(); if (ans<c1+c2) cout<<"No\n";else cout<<"Yes\n"; } } return 0; }