平面图最小割,注意双向边。
#include<cstdio> #include<cstring> #define rep(i,a,b) for(int i=(a);i<=(b);i++) int S,T; struct edge{ int to,cap,rev,nx; }G[6000001]; int n,m,x,p; int lv[2000001],iter[2000001],h[2000001],q[7000001]; int P(int x,int y){return (x-1)*m+y;} int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int Min(int a,int b){return a<b?a:b;} void ae(int s,int e,int w){ G[++p]=(edge){e,w,p+1,h[s]};h[s]=p; } void bfs(int s){ int he=0,ta=0; q[ta++]=s;lv[s]=1; while(he<ta){ int x=q[he++]; for(int i=h[x];i;i=G[i].nx){ int v=G[i].to; if(!lv[v]&&G[i].cap) lv[v]=lv[x]+1,q[ta++]=v; } } } int dfs(int s,int f){ int sum=0; if(s==T) return f; for(int &i=iter[s];i;i=G[i].nx){ int v=G[i].to; if(lv[s]+1==lv[v]&&G[i].cap){ int d=dfs(v,Min(G[i].cap,f)); if(d) sum+=d,f-=d,G[i].cap-=d,G[G[i].rev].cap+=d; if(f==0) return sum; } } return sum; } int dinic(int s,int t){ int fl=0; while(1){ for(int i=S;i<=T;i++)iter[i]=h[i]; memset(lv,0,sizeof(lv)); bfs(s);if(lv[t]==0) return fl; int d=dfs(s,2147483647);while(d>0){fl+=d;d=dfs(s,2147483647);} } } int main(){ n=read();m=read(); S=1,T=P(n,m); rep(i,1,n)rep(j,1,m-1){x=read();ae(P(i,j),P(i,j+1),x);ae(P(i,j+1),P(i,j),x);} rep(i,1,n-1)rep(j,1,m){x=read();ae(P(i,j),P(i+1,j),x);ae(P(i+1,j),P(i,j),x);} rep(i,1,n-1)rep(j,1,m-1){x=read();ae(P(i,j),P(i+1,j+1),x);ae(P(i+1,j+1),P(i,j),x);} printf("%d\n",dinic(S,T)); return 0; }