【洛谷 P2756】 飛行員配對方案問題(二分圖匹配,最大流)
阿新 • • 發佈:2018-12-17
題目連結
這不是裸的二分圖匹配嗎?
而且匈牙利演算法自帶記錄方案。。
但既然是網路流24題,那就用網路流來做吧。
具體就是從源點向左邊每個點連一條流量為1的邊,兩邊正常連邊,流量都是一,右邊所有點向匯點連一條流量為1的邊,然後跑\(Dinic\)就行了。
怎麼記錄方案?列舉左邊所有點連的所有邊,如果剩餘流量為0就是和這條邊那邊的點匹配了咯。
在家直接用線上IDE寫的,一遍過了。
#include <cstdio> #include <queue> using namespace std; #define INF 2147483647 inline int read(){ int s = 0, w = 1; char ch = getchar(); while(ch < '0' || ch > '9'){if(ch == '-')w = -1;ch = getchar();} while(ch >= '0' && ch <= '9') s = s * 10 + ch - '0',ch = getchar(); return s * w; } const int MAXN = 1000010; struct Edge{ int next, from, to, rest; }e[MAXN]; int head[MAXN], num = 1; inline void Add(int from, int to, int flow){ //printf("%d %d\n", from, to); e[++num] = (Edge){ head[from], from, to, flow }; head[from] = num; e[++num] = (Edge){ head[to], to, from, 0 }; head[to] = num; } int flow[MAXN], pre[MAXN], dfn[MAXN]; int h[MAXN], p[MAXN], f[100][100]; int n, m, s, t, a, b, now, Time, ans; queue <int> q; int RoadExist(){ while(q.size()) q.pop(); flow[s] = INF; pre[t] = 0; q.push(s); dfn[s] = ++Time; while(q.size()){ now = q.front(); q.pop(); for(int i = head[now]; i; i = e[i].next) if(e[i].rest && dfn[e[i].to] != Time) dfn[e[i].to] = Time, flow[e[i].to] = min(flow[now], e[i].rest), q.push(e[i].to), pre[e[i].to] = i; } return pre[t]; } int dinic(){ int ans = 0; while(RoadExist()){ ans += flow[t]; now = t; while(now != s){ e[pre[now]].rest -= flow[t]; e[pre[now] ^ 1].rest += flow[t]; now = e[pre[now]].from; } } return ans; } int main(){ s = 99999; t = 100000; n = read(); m = read(); while(233){ a = read(); b = read(); if(a == -1) break; Add(a, b, 1); } for(int i = 1; i <= n; ++i) Add(s, i, 1); for(int i = n + 1; i <= m; ++i) Add(i, t, 1); ans = dinic(); printf("%d\n", ans); for(int i = 1; i <= n; ++i) for(int j = head[i]; j; j = e[j].next) if(!e[j].rest && e[j].to != s) printf("%d %d\n", i, e[j].to); return 0; }