[BZOJ3504]CQOI2014危桥|最大流

来源:互联网 发布:天军软件下载 编辑:程序博客网 时间:2024/05/16 02:00

源向a1b1连流量为2*an2*bn的边,a2b2向汇连流量为2*an2*bn的边,其他边非危桥连inf,危桥连2的边,跑最大流,但是这时满流不一定有解,因为可能有a1流到b2的流这样,所以把b1b2反过来重构图再跑一次最大流,若能满流则有解。证明:假设第一次a1流了x的流到b2,第二次的时候由于是无向图,a1a2流还是2*an-x,那么a1b1x,所以有x的流是b1-a1-b2,所以一样能流到b2。。

#include<cstdio>#include<iostream>#define N 60#define inf 0x3ffffffusing namespace std;struct edge{int e,f,next;}ed[N*N*2];int n,i,j,a1,a2,an,b1,b2,bn,ne,nd,t,a[N],d[N],que[N],u[N],mp[N][N];char s[N];void add(int s,int e,int f){ed[++ne].e=e;ed[ne].f=f;ed[ne].next=a[s];a[s]=ne;}bool bfs(int s,int t){int i,j,head=1,tail=1,get;for (i=0;i<=nd;i++) u[i]=d[i]=0;u[s]=1;que[1]=s;while (head<=tail){get=que[head++];for (j=a[get];j;j=ed[j].next)if (ed[j].f&&!u[ed[j].e]){d[ed[j].e]=d[get]+1;u[ed[j].e]=1;que[++tail]=ed[j].e;}}return d[t]!=0;}int extend(int x,int minf,int t){if (x==t) return minf;int f=minf,del,j;for (j=a[x];j;j=ed[j].next)if (ed[j].f&&d[ed[j].e]==d[x]+1){del=extend(ed[j].e,min(minf,ed[j].f),t);ed[j].f-=del;ed[j^1].f+=del;minf-=del;if (!minf) break;}if (f==minf) d[x]=0;return f-minf;}int dinic(int s,int t){int ans=0;while (bfs(s,t)) ans+=extend(s,inf,t);return ans;}void build(){ne=1;for (int i=0;i<=nd;i++) a[i]=0;add(0,a1,2*an);add(a1,0,0);add(0,b1,2*bn);add(b1,0,0);add(nd,a2,0);add(a2,nd,2*an);add(nd,b2,0);add(b2,nd,2*bn);for (int i=1;i<=n;i++)for (int j=i+1;j<=n;j++)if (mp[i][j]) add(i,j,mp[i][j]),add(j,i,mp[i][j]);}int main(){while (scanf("%d%d%d%d%d%d%d",&n,&a1,&a2,&an,&b1,&b2,&bn)!=EOF){nd=n+1;a1++;a2++;b1++;b2++;for (i=1;i<=n;i++){scanf("%s",s+1);for (j=i+1;j<=n;j++) if (s[j]=='O') mp[i][j]=2;else if (s[j]=='N') mp[i][j]=inf;else mp[i][j]=0;}build();t=dinic(0,nd);if (t<2*an+2*bn) printf("No\n");else{swap(b1,b2);build();t=dinic(0,nd);if (t<2*an+2*bn) printf("No\n");else printf("Yes\n");}}}


0 0
原创粉丝点击