• [洛谷P1345] [USACO5.4]奶牛的电信Telecowmunication


    题目链接:

    奶牛的电信

    题目分析:

    原本以为是一道裸最小割,仔细一看发现是割点……

    把每个点拆成两个点,中间用一条边权为1的边来连接,然后跑最小割即可

    注意源点和汇点拆点后的边权要赋为INF,因为不能直接毁坏源点和汇点

    代码:

    #include<bits/stdc++.h>
    #define N (1000 + 5)
    #define M (4000 + 5)
    #define int long long
    using namespace std;
    inline int read() {
        int cnt = 0, f = 1; char c = getchar();
        while (!isdigit(c)) {if (c == '-') f = -f; c = getchar();}
        while (isdigit(c)) {cnt = (cnt << 3) + (cnt << 1) + c - '0'; c = getchar();}
        return cnt * f;
    }
    int n, m, S, T;
    int tot = 1, first[N], nxt[M], to[M], flow[M], dep[N], cnt[N];
    void Add(int x, int y, int z) {
        nxt[++tot] = first[x], first[x] = tot, to[tot] = y, flow[tot] = z;
    }
    void bfs_(int s) {
        memset(dep, 0xff, sizeof(dep));
        dep[s] = 0;
        cnt[0] = 1;
        queue <int> q;
        q.push(s);
        while (!q.empty()) {
            int p = q.front();
            q.pop();
            for (register int i = first[p]; i >= 2; i = nxt[i]) {
                int v = to[i];
                if (dep[v] == -1) {
                    ++cnt[dep[v] = dep[p] + 1];
                    q.push(v);
                }
            }
        }
    }
    int max_flow;
    
    int dfs_(int p, int f) {
        if (p == T + n) {
    //		cout<<"qwq"<<f<<endl; 
            max_flow += f;
            return f;
        }
        int u = 0;
        for (register int i = first[p]; i >= 2; i = nxt[i]) {
            int v = to[i];
            if (flow[i] && dep[v] == dep[p] - 1) {
                int uu = dfs_(v, min(flow[i], f - u));
                if (uu) {
                    flow[i] -= uu;
                    flow[i ^ 1] += uu;
                    u += uu;
                }
                if (u >= f) return u;
            }
        }
        if (!--cnt[dep[p]]) dep[S] = 2 * n + 1;
        ++cnt[++dep[p]];
        return u;
    }
    int x, y;
    signed main() {
        n = read(); m = read(); S = read(); T = read();
        for (register int i = 1; i <= n; i++) {
            if (i == S || i == T) continue;
            Add(i, i + n, 1), Add(i + n, i, 0);
        }
        Add(S, S + n, 0x3FFFFFFF), Add(S + n, S, 0);
        Add(T, T + n, 0x3FFFFFFF), Add(T + n, T, 0);
        for (register int i = 1; i <= m; i++) {
            x = read(); y = read();
            Add(x + n, y, 0x3FFFFFFF);
            Add(y, x + n, 0);
            Add(y + n, x, 0x3FFFFFFF);
            Add(x, y + n, 0);
        }
        bfs_(T + n);
        while (dep[S] < 2 * n) dfs_(S, 0x3FFFFFFF); 
        printf("%lld", max_flow);
        return 0;
    }
    
  • 相关阅读:
    【JAVA】 04-Java中的多线程
    【刷题】经典的启发式算法
    【刷题】java 常见的几种运行时异常RuntimeException
    【学习总结】认识微服务
    【刷题】知识点与易错点之简单编程思路总结
    【刷题】知识点与易错点- 总
    【刷题】知识点与易错点之数据结构
    【学习总结】《大话数据结构》- 第9章-排序
    LeetCode之“动态规划”:Valid Parentheses && Longest Valid Parentheses
    LeetCode之“动态规划”:Interleaving String
  • 原文地址:https://www.cnblogs.com/kma093/p/11197879.html
Copyright © 2020-2023  润新知