题解:

最小割

跑一下网络流

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=1000005;
struct data{int to,next,v;}e[N*6];
int fi[N],n,m,num,h[N],q[N],ans;
void jb(int x,int y,int z)
{
    e[++num].to=y;
    e[num].v=z;
    e[num].next=fi[x];
    fi[x]=num;
}
int bfs()
{
    memset(h,-1,sizeof(h));
    int t=0,w=1;
    q[t]=1;h[1]=0;
    while (t<w)
     {   
        int now=q[t++];
        for (int i=fi[now];i;i=e[i].next)
         if (e[i].v&&h[e[i].to]<0)
          {
            q[w++]=e[i].to;
            h[e[i].to]=h[now]+1;                 
          }
     }
    if (h[n*m]==-1)return 0;
    return 1;
}
int dfs(int x,int f)
{
    if(x==n*m)return f;
    int w,used=0;
    for (int i=fi[x];i;i=e[i].next)
     if (e[i].v&&h[e[i].to]==h[x]+1)
      {
        w=f-used;
        w=dfs(e[i].to,min(w,e[i].v));
        e[i].v-=w;
        e[i+1].v+=w;
        used+=w;
        if (used==f)return f;
      }
    if (!used)h[x]=-1;
    return used;
}
void dinic()
{
    while(bfs())ans+=dfs(1,0x7fffffff);
}
int main()
{
    scanf("%d%d",&n,&m);
    int x;
    for (int i=1;i<=n;i++)
     for (int j=1;j<m;j++)
      {
        scanf("%d",&x);
        jb(m*(i-1)+j,m*(i-1)+j+1,x);
        jb(m*(i-1)+j+1,m*(i-1)+j,x);
      }
    for (int i=1;i<n;i++)
     for (int j=1;j<=m;j++)
      {
        scanf("%d",&x);
        jb(m*(i-1)+j,m*(i)+j,x);
        jb(m*(i)+j,m*(i-1)+j,x);
      }
    for (int i=1;i<n;i++)
     for (int j=1;j<m;j++)
      {
        scanf("%d",&x);
        jb(m*(i-1)+j,m*(i)+j+1,x);
        jb(m*(i)+j+1,m*(i-1)+j,x);
      }
    dinic();
    printf("%d",ans);
    return 0;
}

 

posted on 2018-03-13 18:43  宣毅鸣  阅读(127)  评论(0编辑  收藏  举报