网络流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;
}
posted @ 2013-04-16 22:23  kedebug  阅读(280)  评论(0编辑  收藏  举报