网络流24题(01)搭配飞行员(最大流)

思路:

设置源点为 0,汇点为 n + 1,源点向飞行员引弧,容量为 1,飞行员和副飞行员引弧,容量为 1,副飞行员向 汇点引弧,容量为 1,求最大流。

 

#include <cstdio>

#include <cstring>

#include <algorithm>

#include <queue>

#include <vector>

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) {}

};



struct ISAP {

    vector<edge> edges;

    vector<int> G[MAXN];

    int s, t, n;

    int d[MAXN], p[MAXN], cur[MAXN], gap[MAXN];

    bool vis[MAXN];



    void clearall(int n) {

        this->n = n;

        edges.clear();

        for (int i = 0; i < n; i++)

            G[i].clear();

    }



    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);

    }



    bool BFS() {

        queue<int> Q;

        memset(d, 0, sizeof(d));

        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 (e.cap > e.flow && !vis[e.from]) {

                    vis[e.from] = true;

                    d[e.from] = d[x] + 1;

                    Q.push(e.from);

                }

            }

        }

        return vis[s];

    }



    int augment() {

        int x = t, f = INFS;

        while (x != s) {

            edge& e = edges[p[x]];

            f = min(f, e.cap - e.flow);

            x = e.from;

        }

        x = t;

        while (x != s) {

            edges[p[x]].flow += f;

            edges[p[x]^1].flow -= f;

            x = edges[p[x]].from;

        }

        return f;

    }



    int maxflow(int s, int t) {

        this->s = s, this->t = t;

        BFS();

        memset(cur, 0, sizeof(cur));

        memset(p, 0, sizeof(p));

        memset(gap, 0, sizeof(gap));

        for (int i = 0; i < n; i++)

            gap[d[i]] += 1;

        int x = s, flow = 0;

        while (gap[s] < n) {

            if (x == t) {

                flow += augment();

                x = s;

            }

            bool flag = false;

            for (int i = cur[x]; i < G[x].size(); i++) {

                edge& e = edges[G[x][i]];

                if (d[x] == d[e.to] + 1 && e.cap > e.flow) {

                    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;

    }

};



ISAP sap;



int main() {

    freopen("flyer.in", "r", stdin);

    freopen("flyer.out", "w", stdout);



    int n, n1;

    scanf("%d%d", &n, &n1);

    int u, v;

    sap.clearall(n + 2);

    while (scanf("%d%d", &u, &v) != EOF) {

        sap.addedge(u, v, 1);

    }



    int s = 0, t = n + 1;

    for (int i = 1; i <= n1; i++)

        sap.addedge(s, i, 1);

    for (int i = n1+1; i <= n; i++)

        sap.addedge(i, t, 1);



    printf("%d\n", sap.maxflow(s, t));

    return 0;

}

你可能感兴趣的:(网络流)