题意
求最小割
题解
Dinic+当前弧优化
#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
int n,m,S,T,cnt=-1,depth[6000001],head[6000001];
int cur[6000001];
struct edge{
int nxt=-1,to,w;
}flow[6000001];
void add(int x,int y,int z){
cnt++;
flow[cnt].to=y;
flow[cnt].w=z;
flow[cnt].nxt=head[x];
head[x]=cnt;
}
bool bfs(){
queue<int> q;
while (!q.empty()) q.pop();
memset(depth,0,sizeof(depth));
depth[S]=1;
q.push(S);
while (!q.empty()){
int u=q.front();
q.pop();
for (int i=head[u];i!=-1;i=flow[i].nxt)
if ((flow[i].w>0)&&(depth[flow[i].to]==0)){
depth[flow[i].to]=depth[u]+1;
q.push(flow[i].to);
}
}
if (depth[T]==0){
return false;
}
return true;
}
int dfs(int u,int dist){
if (u==T) return dist;
for (int &i=cur[u];i!=-1;i=flow[i].nxt){
if ((depth[flow[i].to]==depth[u]+1)&&(flow[i].w!=0)) {
int di=dfs(flow[i].to,min(dist,flow[i].w));
if (di>0){
flow[i].w-=di;
flow[i^1].w+=di;
return di;
}
}
}
return 0;
}
int Dinic(){
int ans=0;
while (bfs()){
memcpy(cur,head,sizeof(head));
while (int d=dfs(S,1e8))
ans+=d;
}
return ans;
}
int point(int x,int y){
return (x-1)*m+y;
}
int main(){
memset(head,-1,sizeof(head));
cin>>n>>m;
S=point(1,1);
T=point(n,m);
int x;
for (int i=1;i<=n;i++)
for (int j=1;j<m;j++){
cin>>x;
add(point(i,j),point(i,j+1),x);
add(point(i,j+1),point(i,j),x);
}
for (int i=1;i<n;i++)
for (int j=1;j<=m;j++){
cin>>x;
add(point(i,j),point(i+1,j),x);
add(point(i+1,j),point(i,j),x);
}
for (int i=1;i<n;i++)
for (int j=1;j<m;j++){
cin>>x;
add(point(i,j),point(i+1,j+1),x);
add(point(i+1,j+1),point(i,j),x);
}
cout<<Dinic();
return 0;
}