注意双向边正反边容量相同
#include<cstdio> #include<cstring> #include<cctype> #include<queue> #define maxn 1000005 #define inf 1000000007 using namespace std; int n,m,S,T,hd,tail,ans,q[maxn],dep[maxn]; int cnt,head[maxn],cur[maxn],nex[maxn*6],to[maxn*6],w[maxn*6]; inline int read(){ char ch=getchar();int x=0,f=1; while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} return x*=f; } inline void addedge(int u,int v,int wi){nex[cnt]=head[u];to[cnt]=v;w[cnt]=wi;head[u]=cnt++;nex[cnt]=head[v];to[cnt]=u;w[cnt]=wi;head[v]=cnt++;} inline int bfs(){ hd=0;q[tail=1]=S; memset(dep,0,sizeof(dep));dep[S]=1; while(hd!=tail){ int u=q[++hd]; for(int j=head[u];~j;j=nex[j])if(!dep[to[j]] && w[j]>0){dep[to[j]]=dep[u]+1,q[++tail]=to[j];} if(u==T)return 1; } return dep[T]; } inline int dfs(int u,int flow){ if(u==T)return flow; int ans=0,x=0; for(int &i=cur[u];~i;i=nex[i]){ int v=to[i]; if(dep[u]+1==dep[v] && w[i]>0){ x=dfs(v,min(flow-ans,w[i])); w[i]-=x;w[i^1]+=x; ans+=x; if(ans==flow)return flow; } } if(ans==0)dep[x]=0; return ans; } inline void dinic(){ while(bfs()){for(int i=S;i<=T;i++)cur[i]=head[i];ans+=dfs(S,inf);} } int main(){ memset(head,-1,sizeof(head)); n=read(),m=read(); S=1,T=n*m;int x; for(int i=1;i<=n;i++)for(int j=1;j<m;j++)addedge((i-1)*m+j,(i-1)*m+j+1,read()); for(int i=1;i<n;i++)for(int j=1;j<=m;j++)addedge((i-1)*m+j,i*m+j,read()); for(int i=1;i<n;i++)for(int j=1;j<m;j++)addedge((i-1)*m+j,i*m+j+1,read()); dinic(); printf("%d",ans); return 0; }