P2756 飞行员配对方案问题

原题链接

  • 题解:建图就类似二分图找最大匹配,然后如果输出方案的话,那就是残留网络中流量为0的正向边就是使用的,所以直接找即可。
  • 代码:
#include <iostream>
#include <queue>
#include <map>
#include <cstring>
using namespace std;
#define int long long
map<int,int>mp;
const int N = 2200, M = 220000;
const int inf = 99999999999;
int n, nn, S, T;
int h[M], ne[M], to[M], f[M], idx;
void add(int u, int v, int w) {
    ne[idx] = h[u], to[idx] = v, f[idx] = w, h[u] = idx ++;
    ne[idx] = h[v], to[idx] = u, f[idx] = 0, h[v] = idx ++;
}
int d[N],cur[N];
queue<int>q;
bool bfs() {
    while (!q.empty())q.pop();
    q.push(S);
    memset(d, -1, sizeof d);
    d[S] = 0;
    cur[S] = h[S];
    while (!q.empty()) {
        auto u = q.front();
        q.pop();
        for (int i = h[u]; ~i; i = ne[i]) {
            int v= to[i];
            if (d[v] == -1 && f[i]) {
                d[v] = d[u] + 1;
                cur[v] = h[v];
                if (v == T)return 1;
                q.push(v);
            }
        }
    }
    return 0;
}
int ans[N];
int ans_cnt = 0;
int dfs(int u, int limit) {
    if (u == T)return limit;
    int flow = 0;
    for (int i = cur[u]; ~i && flow < limit; i = ne[i]) {
        int v = to[i];
        cur[u] = i;
        if (f[i] && d[v] == d[u] + 1) {
            int t = dfs(v, min(f[i], limit - flow));
            if (!t)d[v] = -1;
            f[i] -= t;
            f[i^1] += t;
            flow += t;
        }
    }
    if (u > n && u <= nn && flow ==1) {
        ans[++ans_cnt] = u;
    } else if (u >0 && u <= n && flow == 1) {
        ans[++ans_cnt] = u;
    }
    return flow;
}
int dinic() {
    int ret = 0, flow;
    while (bfs()) {while (flow = dfs(S, inf))ret += flow;}

    return ret;
}
signed main() {
    memset(h, -1, sizeof h);
    scanf("%lld%lld%", &n, &nn);
    int u, v;
    S = 0, T = nn + 1;
    while (scanf("%lld%lld", &u, &v)) {
        if (u == -1 && v == -1)break;
        add(u, v , 1);
    }
    for (int i = 1; i <= n; i ++) {
        add(S, i, 1);
    }
    for (int j = n + 1; j <= nn; j ++) {
        add(j, T, 1);
    }
    printf("%lld
", dinic());
    for (int i = 0; i < idx; i += 2) {
        if (to[i ^ 1] <= n && to[i]> n && !f[i]) {
            printf("%d %d
", to[i ^ 1], to[i]);
        }
    }
}
原文地址:https://www.cnblogs.com/Xiao-yan/p/14651640.html