bzoj1412: [ZJOI2009]狼和羊的故事

最小割,边max为60w条!

虚拟源点连狼,容量为INF,羊连虚拟汇点,容量为INF。

狼和空格向旁边的空格和羊连容量为1的边

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 100 + 10;
const int maxm = 60000 + 10;
const int maxv = 10000 + 10;
const int INF = 0x3f3f3f3f;

int n,m,e,vid,S,T;
int h[maxv],v[maxm],next[maxm],f[maxm];
int dist[maxv],gap[maxv];
int a[maxn][maxn],id[maxn][maxn];
int dx[] = {1,0,-1,0}; int dy[] = {0,1,0,-1};

void add(int a,int b,int F) {
    v[e] = b; next[e] = h[a]; f[e] = F; h[a] = e++;
    v[e] = a; next[e] = h[b]; f[e] = 0; h[b] = e++;
}

void build() {
    scanf("%d%d",&n,&m);
    memset(h,-1,sizeof(h));
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= m; j++) {
            scanf("%d",&a[i][j]);
            id[i][j] = ++vid;
        }    
    S = ++vid; T = ++vid;
    
    for(int i = 1; i <= n; i++)
    for(int j = 1; j <= m; j++) {
        if(a[i][j] == 1) add(S,id[i][j],INF);
        else if(a[i][j] == 2) add(id[i][j],T,INF);
        
        for(int d = 0,x,y; d < 4; d++)
            if(id[x=i+dx[d]][y=j+dy[d]])
                if(a[i][j] != 2 && a[x][y] != 1) 
                    add(id[i][j],id[x][y],1);
    }
}

int ISAP(int u,int flow) {
    if(u == T) return flow;
    
    int cur = 0,aug,mindist = vid;
    for(int i =h[u];~i;i=next[i]) 
        if(f[i] && dist[u] == dist[v[i]] + 1) {
            aug = ISAP(v[i],min(f[i],flow-cur));
            f[i] -= aug;
            f[i^1] += aug;
            cur += aug;
            if(cur == flow || dist[S] >= vid) {
                return cur;
            }
        }
    
    if(cur == 0) {
        if(!--gap[dist[u]]) {
            dist[S] = vid;
            return cur;
        }
        for(int i = h[u];~i;i=next[i]) if(f[i])
            mindist = min(mindist,dist[v[i]]);
        ++gap[dist[u]=mindist+1];
    }
    return cur;
}

int min_cut1() {
    gap[0] = vid;
    int res = 0;
    while(dist[S] < vid) {
        res += ISAP(S,INF);
    }
    return res;
}

void solve() {
    printf("%d\n",min_cut1());
}

int main() {
    build();
    solve();
    return 0;
}
posted @ 2016-04-13 13:03  invoid  阅读(139)  评论(0编辑  收藏  举报