bzoj 1001
裸的 dinic 求最小割。
#include"cstdio" #include"cctype" #include"vector" #include"cstring" using namespace std; int read() { int c,x=0; while(!isdigit(c=getchar())); while(x=x*10+c-'0',isdigit(c=getchar())); return x; } struct edge { int t,w; edge(int t,int w):t(t),w(w){} }; vector<edge> e; vector<int>to[1001*1001]; void add(int u,int v,int w) { e.push_back(edge(v,w)); to[u].push_back(e.size()-1); e.push_back(edge(u,w)); to[v].push_back(e.size()-1); } int qu[1001*1001],dis[1001*1001]; bool vis[1001*1001]; #define l to[f].size() #define k e[to[f][j]].w #define q e[to[f][j]].t bool bfs(int n,int m) { memset(vis,0,sizeof vis); int h,t; h=t=0; qu[t++]=1; dis[1]=1; vis[1]=1; while(h<t) { int f=qu[h++]; for(int j=0;j<l;j++) if(!vis[q] && k) vis[q]=1,dis[q]=dis[f]+1,qu[t++]=q; } return vis[n*m]; } int dfs(int n,int m,int f,int w) { if(f==n*m) return w; int res=0; for(int j=0;w && j<l;j++) if(k && dis[q]==dis[f]+1) { int kk=dfs(n,m,q,min(w,k)); if(!kk) dis[q]=-1; else w-=kk,res+=kk,k-=kk,e[to[f][j]^1].w+=kk; } return res; } int main() { int n=read(),m=read(),ans=0; for(int i=0;i<n;i++) for(int j=1;j<m;j++) add(i*m+j,i*m+j+1,read()); for(int i=0;i<n-1;i++) for(int j=1;j<=m;j++) add(i*m+j,(i+1)*m+j,read()); for(int i=0;i<n-1;i++) for(int j=1;j<m;j++) add(i*m+j,(i+1)*m+j+1,read()); while(bfs(n,m)) ans+=dfs(n,m,1,2e9); printf("%d",ans); return 0; }