zoukankan      html  css  js  c++  java
  • 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
    ", Dinic());
        return 0;
    }
    /*
    */
  • 相关阅读:
    java—— 字节流
    20-转>ES6转ES5的实现原理
    18-检验闭包是否真正理解?
    17-数组中去除基本数据类型和NaN的重复项(并保证原有数组顺序)
    16-实现一个Promise.all 和 Promise.race
    14-数组求和之递归方式
    13-斐波那契数列
    12-找到数组中的两项的和等于传入的指定数
    11-合并两个有序数组
    10-判断两个对象是否相等(有点类型every的实现)
  • 原文地址:https://www.cnblogs.com/CJLHY/p/9276464.html
Copyright © 2011-2022 走看看