[Luogu2756] [網路流24題]飛行員配對方案問題
阿新 • • 發佈:2019-01-05
這應該是比裸的一個網路流/二分圖匹配了。
直接跑一遍Dinic求出最大流。再依次遍歷所有二分圖上的邊,如果剩餘流量是0,則說明兩者相互匹配,作為一組輸出。
#include <queue> #include <cstdio> #include <cstring> #include <algorithm> #define MAXN 205 #define MAXM 20005 struct edge { int u,v,next,c; }G[MAXM]; int head[MAXN],cur[MAXN]; int d[MAXN],rec[MAXM]; int N,M,S,T; int tot = -1,cnt = 0; inline void add(int u,int v,int c) { G[++tot].u = u; G[tot].v = v; G[tot].c = c; G[tot].next = head[u]; head[u] = tot; } inline bool bfs() { std::memset(d,0,sizeof(d)); std::queue < int > q; d[S] = 1; q.push(S); while(!q.empty()) { int u = q.front(); q.pop(); for(int i=head[u];i!=-1;i=G[i].next) { int v = G[i].v; if(d[v]==0&&G[i].c>0) { d[v] = d[u] + 1; q.push(v); } } } return d[T]; } int dfs(int u,int a) { if(u==T) return a; int flow = 0,temp; for(int& i=cur[u];i!=-1;i=G[i].next) { int v = G[i].v; if(d[u]+1==d[v]&&G[i].c&&(temp = dfs(v,std::min(a,G[i].c)))>0) { flow += temp; a -= temp; G[i].c -= temp; G[i^1].c += temp; if(a==0) break; } } return flow; } inline int dinic() { int flow = 0; for(int i=1;i<=N;++i) { add(S,i,1); add(i,S,0); } for(int i=N+1;i<=M;++i) { add(i,T,1); add(T,i,0); } while(bfs()) { for(int i=1;i<=M+2;++i) cur[i] = head[i]; flow += dfs(S,2147483647); } return flow; } int main() { int u = 0,v = 0; scanf("%d%d",&N,&M); std::memset(head,-1,sizeof(head)); while(scanf("%d%d",&u,&v)&&(u!=-1)&&(v!=-1)) { add(u,v,1); add(v,u,0); rec[++cnt] = tot - 1 ; } S = M + 1; T = S + 1; int temp = dinic(); if(temp) { printf("%d\n",temp); for(int i=1;i<=cnt;++i) { if(G[rec[i]].c==0) printf("%d %d\n",G[rec[i]].u,G[rec[i]].v); } } else puts("No Solution!"); return 0; }