1. 程式人生 > >【洛谷 P2756】 飛行員配對方案問題(二分圖匹配,最大流)

【洛谷 P2756】 飛行員配對方案問題(二分圖匹配,最大流)

題目連結
這不是裸的二分圖匹配嗎?
而且匈牙利演算法自帶記錄方案。。
但既然是網路流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;
}