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;

}

你可能感兴趣的:(ping)