• UVA-10480 Sabotage(最小割,割边方案)


    题目链接:UVA-10480 Sabotage

    题意

    给出一个图的连边(无向边)和割断每条边的花费,要割掉一些边令结点1和结点2不连通,求最小花费的切割方案。


    思路

    在原图上以结点1为源点,结点2为汇点,边的花费为容量建立流网络,最小割即为最小花费。

    设割边将流网络的结点分为$S$和$T$两个集合。Ford-Fulkerson方法求最大流后的残量网络中,从源点开始dfs,每次走残余容量大于$0$的边,即可找到所有$S$集合内的结点。所有边$(u,v)$中,若$uin S, vin T$,则$(u,v)$为割边。


    代码实现

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <queue>
    using std::queue;
    const int INF = 0x3f3f3f3f, N = 60, M = 1100;
    int head[N], d[N];
    int s, t, tot, maxflow;
    bool vis[N];
    struct Edge
    {
        int to, cap, nex;
    } edge[M];
    queue<int> q;
    void add(int x, int y, int z) {
        edge[++tot].to = y, edge[tot].cap = z, edge[tot].nex = head[x], head[x] = tot;
    }
    bool bfs() {
        memset(d, 0, sizeof(d));
        while (q.size()) q.pop();
        q.push(s); d[s] = 1;
        while (q.size()) {
            int x = q.front(); q.pop();
            for (int i = head[x]; i; i = edge[i].nex) {
                int v = edge[i].to;
                if (edge[i].cap && !d[v]) {
                    q.push(v);
                    d[v] = d[x] + 1;
                    if (v == t) return true;
                }
            }
        }
        return false;
    }
    int dinic(int x, int flow) {
        if (x == t) return flow;
        int rest = flow, k;
        for (int i = head[x]; i && rest; i = edge[i].nex) {
            int v = edge[i].to;
            if (edge[i].cap && d[v] == d[x] + 1) {
                k = dinic(v, std::min(rest, edge[i].cap));
                if (!k) d[v] = 0;
                edge[i].cap -= k;
                edge[i^1].cap += k;
                rest -= k;
            }
        }
        return flow - rest;
    }
    void init() {
        tot = 1, maxflow = 0;
        s = 1, t = 2;
        memset(head, 0, sizeof(head));
        memset(vis, false, sizeof(vis));
    }
    void dfs(int u) {
      vis[u] = true;
      for (int i = head[u]; i; i = edge[i].nex) {
        int v = edge[i].to;
        if (!vis[v] && edge[i].cap) dfs(v);
      }
    }
    
    int main() {
        int n, m;
        while (~scanf("%d %d", &n, &m) && (n || m)) {
            init();
            for (int i = 0, u, v, z; i < m; i++) {
                scanf("%d %d %d", &u, &v, &z);
                add(u, v, z);
                add(v, u, z);
            }
            while (bfs()) maxflow += dinic(s, INF);
            dfs(s);
            for (int i = 1; i <= n; i++) {
                if (vis[i]) {
                    for (int j = head[i]; j; j = edge[j].nex) {
                        if (!vis[edge[j].to]) printf("%d %d
    ", i, edge[j].to);
                    }
                }
            }
            puts("");
        }
        return 0;
    }
    View Code
    作者:_kangkang
    本文版权归作者和博客园共有,欢迎转载,但必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。
  • 相关阅读:
    CF(437C)The Child and Toy(馋)
    Android大放送干:书籍、过程、工具等各种全
    UVa 121
    ONOS系统架构演进,实现高可用性解决方案
    PowerDesigner 的常用小技巧 转
    现代团队必须是非常非常有活力、有激情同时又有向心力、有限属技能的团队。
    关于团队管理的心得体会 转
    Delphi 编译错误信息表
    财务基础 入门
    Sql Server CONVERT获取当前日期及日期样式
  • 原文地址:https://www.cnblogs.com/kangkang-/p/11333032.html
Copyright © 2020-2023  润新知