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;
}

 

posted @ 2018-02-26 14:10  312432424  阅读(141)  评论(0编辑  收藏  举报