飞行员配对方案问题

来源:互联网 发布:保护眼睛的软件 编辑:程序博客网 时间:2024/04/28 15:07

飞行员配对方案问题


简要题意:

给出一个二分图,求最大匹配方案。

数据范围:

n100

算法:

网络流

建图:
  • 建出题目中所给的二分图,建立源点S,汇点T。
  • S向集合X中的点连流量为1的边
  • 集合Y向T中的点连流量为1的边
  • 集合X和Y之间的边流量1的边
输方案:
  • 直接将两个集合之间流量为1的边的输出…
代码:
#include <cstdio>#include <queue>#include <cstring>using namespace std;int rd() {    int x = 0, f = 1; char c = getchar();    while (c > '9' || c < '0') f = c == '-' ? - 1: 1, c = getchar();    while (c >= '0' && c <= '9') x = x * 10 + c - 48, c = getchar();    return x * f;}#define pc putcharvoid wt(int x) {    if (x >= 10) wt(x / 10);    pc(x % 10 + 48);}const int N = 300;const int inf = 0x7f7f7f7f;int head[N], d[N], cnt = 1, n, m, S, T;bool vis[N];struct edge{    int nxt, to, w;}e[N * N * 2];void add_edge(int u, int v, int w) {    e[++cnt].nxt = head[u], e[head[u] = cnt].to = v, e[cnt].w = w;    e[++cnt].nxt = head[v], e[head[v] = cnt].to = u, e[cnt].w = 0;  }bool bfs() {    queue <int> q;    memset(d, 0, sizeof d);    q.push(S), d[S] = 1;    while (!q.empty()) {        int u = q.front(); q.pop();        for (int i = head[u]; i; i = e[i].nxt) {            int v = e[i].to;            if (e[i].w && !d[v]) d[v] = d[u] + 1, q.push(v);        }    }    return d[T];}int dfs(int u, int f) {    if (u == T || !f) return f;    int t = 0;    for (int i = head[u]; i; i = e[i].nxt) {        int v = e[i].to;        if (e[i].w && d[v] == d[u] + 1) {            int w = dfs(v, min(f - t, e[i].w));            if (!w) continue;            e[i].w -= w, e[i ^ 1].w += w, t += w;            if (f == t) return t;        }    }    if (!t) d[u] = 0;    return t;}int dinic() {    int re = 0;    while (bfs()) re += dfs(S, inf);    return re;}int main() {//  freopen("example.in", "r", stdin);    n = rd(), m = rd();    S = 0, T = n + m + 1;    for (int i = 1; i <= n; i ++) add_edge(S, i, 1);    for (int i = n + 1; i <= m; i ++) add_edge(i, T, 1);    while (1) {        int i = rd(), j = rd();        if (i == -1) break;        add_edge(i, j, 1);    }    wt(dinic()), pc(10);    for (int i = head[S]; i; i = e[i].nxt) if (!e[i].w && e[i].to) vis[e[i].to] = 1;    for (int i = 1; i <= n; i ++) if (vis[i]) {        wt(i), pc(32);        for (int j = head[i]; j; j = e[j].nxt) if (!e[j].w && e[j].to) {            wt(e[j].to), pc(10);            break;        }    }    return 0;}
原创粉丝点击