bzoj 1412 最小割

思路:一个篱笆的作用就是堵死一条路,我们将S与狼建边,权值为inf, 将羊与T建边,权值为inf, 每个点与其可以到的路建边,权值为1,

然后跑最小割,因为如果S到T有通路说明狼肯定可以到羊,每一个割代表一个篱笆。

#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define pii pair<int, int>

using namespace std;

const int N = 2e4 + 7;
const int M = 2e5 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;

int n, m, S, T, tot, level[N], head[N], a[101][101], id[101][101];

int dx[] = {0, 0, 1, -1}, dy[] = {1, -1, 0, 0};
struct Edge {
    int to, w, nx;
}edge[M << 1];

void add(int u, int v, int w) {
    edge[tot].to = v;
    edge[tot].w = w;
    edge[tot].nx = head[u];
    head[u] = tot++;

    edge[tot].to = u;
    edge[tot].w = 0;
    edge[tot].nx = head[v];
    head[v] = tot++;
}

bool bfs() {
    memset(level, 0, sizeof(level));
    queue<int> que;
    que.push(S), level[S] = 1;

    while(!que.empty()) {
        int u = que.front(); que.pop();
        if(u == T) return true;

        for(int i = head[u]; ~i; i = edge[i].nx) {
            int v = edge[i].to, w = edge[i].w;
            if(level[v] || w <= 0) continue;
            level[v] = level[u] + 1;
            que.push(v);
        }
    }
    return false;
}

int dfs(int u, int p) {
    if(u == T) return p;
    int ret = 0;
    for(int i = head[u]; ~i; i = edge[i].nx) {
        int v = edge[i].to, w = edge[i].w;
        if(level[v] != level[u] + 1 || w <= 0) continue;
        int f = dfs(v, min(p - ret, w));
        ret += f;
        edge[i].w -= f;
        edge[i ^ 1].w += f;
        if(ret == p) break;
    }

    if(!ret) level[u] = 1;
    return ret;
}

int Dinic() {
    int ans = 0;
    while(bfs()) ans += dfs(S, inf);
    return ans;
}

void init() {
    tot = 0;
    memset(head, -1, sizeof(head));
}

bool check(int x, int y) {
    if(x < 1 || x > n) return false;
    if(y < 1 || y > m) return false;
    return true;
}

int main() {
    init();
    scanf("%d%d", &n, &m);
    S = 0, T = n * m + 1;
    for(int i = 1; i <= n; i++) {
        for(int j = 1; j <= m; j++) {
            scanf("%d", &a[i][j]);
            id[i][j] = (i - 1) * 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 i = 1; i <= n; i++) {
        for(int j = 1; j <= m; j++) {
            for(int k = 0; k < 4; k++) {
                int x = i + dx[k], y = j + dy[k];
                if(check(x, y) && (a[i][j] != a[x][y] || !a[i][j] && !a[x][y])) {
                    add(id[i][j], id[x][y], 1);
                }
            }
        }
    }

    printf("%d\n", Dinic());
    return 0;
}
/*
*/

 

posted @ 2018-07-07 10:04  NotNight  阅读(137)  评论(0编辑  收藏  举报