分析
显然答案是最小割。
然后dinic卡一卡过去了。
其实是懒得写转对偶图:正解
(dinic原来写的是vector,后来改的比较鬼畜
代码
#include <bits/stdc++.h> using namespace std; const int maxn=1e6+5, INF=2e9; struct Edge{ int from,to,cap,flow; }; int siz=0; Edge edges[6*maxn]; int G[maxn][7]; int que[maxn]; int d[maxn], vis[maxn], cur[maxn]; int s,t; void Addedge(int a,int b,int c){ // edges.push_back((Edge){a,b,c,0}); edges.push_back((Edge){b,a,c,0}); // int m=edges.size()-1; G[a].push_back(m-1); G[b].push_back(m); edges[siz++]=(Edge){a,b,c,0}; edges[siz++]=(Edge){b,a,c,0}; G[a][++G[a][0]]=siz-2; G[b][++G[b][0]]=siz-1; } bool BFS(){ memset(vis,0,sizeof(vis)); memset(que,0,sizeof(que)); que[1]=s; d[s]=0; vis[s]=1; int l=1,r=2; while(l<r){ int x=que[l]; l++; for(int i=1;i<=G[x][0];i++){ Edge v=edges[G[x][i]]; if(!vis[v.to] && v.flow<v.cap){ vis[v.to]=1; d[v.to]=d[x]+1; que[r++]=v.to; } } } return vis[t]; } int DFS(int x, int a){ if(x==t || a==0) return a; int flow=0, f; for(int& i=cur[x]; i<=G[x][0]; i++){ Edge& v=edges[G[x][i]]; if(d[x]+1==d[v.to] && (f=DFS(v.to,min(a,v.cap-v.flow)))){ v.flow+=f; edges[G[x][i]^1].flow-=f; if(!f) {d[v.to]=-1;continue;} flow+=f; a-=f; if(a==0) break; } } return flow; } int Maxflow() { int flow=0; while(BFS()){ for(int i=0;i<maxn;i++) cur[i]=1; flow+=DFS(s,INF); } return flow; } inline int getint() { int w=0,q=0; char c=getchar(); while((c<‘0‘ || c>‘9‘) && c!=‘-‘) c=getchar(); if (c==‘-‘) q=1, c=getchar(); while (c>=‘0‘ && c<=‘9‘) w=w*10+c-‘0‘, c=getchar(); return q ? -w : w; } int main() { int n,m; scanf("%d%d",&n,&m); if(n==1&&m==1){ puts("0"); return 0; } s=1; t=n*m; int capp; for(int i=0;i<n;i++){ for(int j=1;j<m;j++){ capp=getint(); Addedge(i*m+j,i*m+j+1,capp); // printf("*** %d %d %d\n",i*m+j,i*m+j+1,capp); } } for(int i=1;i<n;i++){ for(int j=1;j<=m;j++){ capp=getint(); Addedge(m*(i-1)+j,i*m+j,capp); // printf("*** %d %d %d\n",m*(i-1)+j,i*m+j,capp); } } for(int i=1;i<n;i++){ for(int j=1;j<m;j++){ capp=getint(); Addedge(m*(i-1)+j,i*m+j+1,capp); // printf("*** %d %d %d\n",m*(i-1)+j,i*m+j+1,capp); } } printf("%d\n",Maxflow()); return 0; }