【bzoj1001】[BeiJing2006]狼抓兔子 最小割

最小割板子,注意的是邊要開點的6倍,因爲一個點三條路再乘2就是6.

#include<iostream>
#include<queue>
#include<cstdio>
#include<cstring>
#include<cctype>
#define inf 0x3f3f3f3f
#define ll long long 
#define N 1010000
using namespace std;
queue<int> q;
int head[N*6],nxt[N*6],to[N*6],c[N*6],cur[N],depth[N],n,m,ans,ToT=1;
int read() {
    int ret=0;char ch=getchar();
    for (;!isdigit(ch);ch=getchar());
    for (;isdigit(ch);ch=getchar()) ret=ret*10+ch-'0';
    return ret;
}
void add_edge(int x,int y,int z) {to[++ToT]=y;c[ToT]=z;nxt[ToT]=head[x];head[x]=ToT;}
void insert(int x,int y,int z){add_edge(x,y,z);add_edge(y,x,z);}
bool bfs() {
    memset(depth,0,sizeof(depth));
    depth[1]=1;q.push(1);
    for (;q.size();) {
        int x=q.front();q.pop();
        for (int i=head[x];i;i=nxt[i]) 
            if (depth[to[i]]==0&&c[i]) 
                depth[to[i]]=depth[x]+1,q.push(to[i]);
    }
    return depth[n*m];
}
int dfs(int x,int f) {
    if (x==n*m) return f;
    int w=0,used=0;
    for (int& i=cur[x];i;i=nxt[i]) {
        if (depth[to[i]]==depth[x]+1) {
            w=f-used;w=dfs(to[i],min(c[i],w));
            used+=w;c[i]-=w;c[i^1]+=w;
            if (used==f) return f;
        }
    }
    if (used==0) depth[x]=-1;
    return used;
}
int main() {
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++)
        for (int j=1;j<m;j++) {
            int x=read();
            insert((i-1)*m+j,(i-1)*m+j+1,x);
        }
    for (int i=1;i<n;i++)
        for (int j=1;j<=m;j++) {
            int x=read();
            insert((i-1)*m+j,i*m+j,x);
        }
    for (int i=1;i<n;i++)
        for (int j=1;j<m;j++) {
            int x=read();
            insert((i-1)*m+j,i*m+j+1,x);
        }
    for (;bfs();) {
        for (int i=1;i<=n*m;i++) cur[i]=head[i];
        ans+=dfs(1,inf);
    }
    printf("%d\n",ans);
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章