zoukankan      html  css  js  c++  java
  • UVa 11248 Frequency Hopping(最小割入门)

    题意:

    给定一个有向网络,每条边均有一个容量。问是否存在一个点 1 到点 N 流量为 C 的流。如果不存在,是否可以恰好修改一条弧的容量,使得存在这样的流。

    思路:

    1. 首先求最大流,若最大流大于 C ,则直接输出即可。如果不大于 C 则需要修改最小割里面的弧;

    2. 关于如何求最小割:求出最大流之后,S->T 已经不存在一条增广路径了。但是仍然按照增广路径的走法,遍历出分别包含 S T 的点集;

    3. 关于上面可以反向来理解:如果点集 T 中有一个点位于点集 S,则增加这两点之间的流量就能继续找到一条增广路径,这显然是违背最大流的;

    4. 修改割里面的弧,每次求出相应的最大流即可。中间用到 2 点优化,一是在以前的最大流基础上增广,二是每次求最大流只需要求是否满足需求即可;

     

    #include <cstdio>
    #include <cstring>
    #include <vector>
    #include <queue>
    #include <algorithm>
    using namespace std;
    
    const int MAXN = 110;
    const int INFS = 0x3FFFFFFF;
    
    struct edge {
        int from, to, cap, flow;
        edge(int _from, int _to, int _cap, int _flow) 
            : from(_from), to(_to), cap(_cap), flow(_flow) {}
        bool operator < (const edge& rhs) const {
            if (from == rhs.from) return to < rhs.to;
            return from < rhs.from;
        }
    };
    
    class ISAP {
    public:
        void clearall(int n) {
            this->n = n;
            for (int i = 0; i < n; i++)
                G[i].clear();
            edges.clear();
        }
        bool bfs() {
            queue<int> Q;
            d[t] = 0;
            memset(vis, false, sizeof(vis));
            vis[t] = true;
            Q.push(t);
            while (!Q.empty()) {
                int x = Q.front(); Q.pop();
                for (int i = 0; i < G[x].size(); i++) {
                    edge& e = edges[G[x][i]^1];
                    if (!vis[e.from] && e.cap > e.flow) {
                        vis[e.from] = true;
                        d[e.from] = d[x] + 1;
                        Q.push(e.from);
                    }
                }
            }
            return vis[s];
        }
    
        void addedge(int u, int v, int cap) {
            edges.push_back(edge(u, v, cap, 0));
            edges.push_back(edge(v, u, 0, 0));
            G[u].push_back(edges.size() - 2);
            G[v].push_back(edges.size() - 1);
        }
        int augment() {
            int x = t, a = INFS;
            while (x != s) {
                edge& e = edges[p[x]];
                a = min(a, e.cap - e.flow);
                x = e.from;
            }
            x = t;
            while (x != s) {
                edges[p[x]].flow += a;
                edges[p[x]^1].flow -= a;
                x = edges[p[x]].from;
            }
            return a;
        }
        int maxflow(int s, int t, int need) {
            this->s = s, this->t = t;
            bfs();
            memset(gap, 0, sizeof(gap));
            for (int i = 0; i < n; i++) 
                cur[i] = 0, gap[d[i]] += 1;
    
            int x = s, flow = 0;
            while (d[s] < n) {
                if (x == t) {
                    flow += augment();
                    if (flow >= need) return flow;
                    x = s;
                }
                bool flag = false;
                for (int i = cur[x]; i < G[x].size(); i++) {
                    edge& e = edges[G[x][i]];
                    if (e.cap > e.flow && d[x] == d[e.to] + 1) {
                        flag = true;
                        cur[x] = i;
                        p[e.to] = G[x][i];
                        x = e.to;
                        break;
                    }
                }
                if (!flag) {
                    int m = n - 1;
                    for (int i = 0; i < G[x].size(); i++) {
                        edge& e = edges[G[x][i]];
                        if (e.cap > e.flow)
                            m = min(m, d[e.to]);
                    }
                    if (--gap[d[x]] == 0) break;
                    gap[d[x] = m+1] += 1;
                    cur[x] = 0;
                    if (x != s) x = edges[p[x]].from;
                }
            }
            return flow;
        }
        void mincut(vector<int>& cut) {
            bfs();
            for (int i = 0; i < edges.size(); i++) {
                edge& e = edges[i];
                if (!vis[e.from] && vis[e.to] && e.cap > 0)
                    cut.push_back(i);
            }
        }
        void reduce() {
            for (int i = 0; i < edges.size(); i++)
                edges[i].cap -= edges[i].flow;
        }
        void clearflow() {
            for (int i = 0; i < edges.size(); i++)
                edges[i].flow = 0;
        }
    public:
        int n, s, t;
        vector<edge> edges;
        vector<int> G[MAXN];
        int p[MAXN], d[MAXN], cur[MAXN], gap[MAXN];
        bool vis[MAXN];
    };
    
    ISAP sap;
    
    int main() {
        int n, e, c, cases = 0;
        while (scanf("%d%d%d", &n, &e, &c) && n) {
            sap.clearall(n);
            while (e--) {
                int u, v, fp;
                scanf("%d%d%d", &u, &v, &fp);
                sap.addedge(u - 1, v - 1, fp);
            }
            int flow = sap.maxflow(0, n - 1, INFS);
            printf("Case %d: ", ++cases);
            if (flow >= c) {
                printf("possible\n");
            } else {
                vector<int> cut;
                vector<edge> ans;
                sap.mincut(cut);
                sap.reduce();
                for (int i = 0; i < cut.size(); i++) {
                    edge& e = sap.edges[cut[i]];
                    sap.clearflow();
                    e.cap = c;
                    if (flow + sap.maxflow(0, n - 1, c - flow) >= c)
                        ans.push_back(e);
                    e.cap = 0;
                }
                if(ans.empty()) 
                    printf("not possible\n");
                else {
                    sort(ans.begin(), ans.end());
                    printf("possible option:(%d,%d)", ans[0].from + 1, ans[0].to + 1);
                    for(int i = 1; i < ans.size(); i++)
                        printf(",(%d,%d)", ans[i].from + 1, ans[i].to + 1);
                    printf("\n");
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    安装express 新建项目遇到问题汇总
    Java IO
    python3基础之“函数(1)”
    python3基础之“小练习(3)”
    python3基础之“小练习(2)”
    python3基础之“小练习(1)”
    linux命令
    1.环境安装部署汇总
    阶段13-直播~
    docker环境问题
  • 原文地址:https://www.cnblogs.com/kedebug/p/3016801.html
Copyright © 2011-2022 走看看