飞行员配对方案问题
这道题明显是二分图匹配……(因为我至今不会写匈牙利我就跑了遍dinic)
非常的明显,自己设定一个原点和汇点。把原点向所有的外籍飞行员连容量为1的边,所有的英国飞行员向汇点连容量为1的边,中间的边按题目描述,给你一条你就建一条容量为1的边。
之后直接跑网络流。至于最后怎么判断哪几个飞行员是配对的,直接判断那些连在中间的边,如果其反向边的流量不为0就说明这条边上面有流量,也就说明它被跑过。
反正这题有spj可以直接过。
#include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #include<queue> #define rep(i,a,n) for(int i = a;i <= n;i++) #define per(i,n,a) for(int i = n;i >= a;i--) #define enter putchar('\n') using namespace std; const int M = 100005; const int INF = 1e9; typedef long long ll; int read() { int ans = 0,op = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') op = -1; ch = getchar(); } while(ch >= '0' && ch <= '9') { ans *= 10; ans += ch - '0'; ch = getchar(); } return ans * op; } struct edge { int next,to,v,from; }e[M]; int m,n,head[M],ecnt = -1,deep[M],maxflow,x,y,source,sink,sum,cur[M]; queue <int> q; void add(int x,int y,int z) { e[++ecnt].to = y; e[ecnt].v = z; e[ecnt].from = x; e[ecnt].next = head[x]; head[x] = ecnt; } bool bfs(int s,int t) { memset(deep,-1,sizeof(deep)); while(!q.empty()) q.pop(); rep(i,0,n+1) cur[i] = head[i]; deep[s] = 0,q.push(s); while(!q.empty()) { int k = q.front();q.pop(); for(int i = head[k];i != -1;i = e[i].next) { if(deep[e[i].to] == -1 && e[i].v) deep[e[i].to] = deep[k] + 1,q.push(e[i].to); } } if(deep[t] == -1) return 0; else return 1; } int dfs(int s,int t,int limit) { if(!limit || s == t) return limit; int flow = 0; for(int i = cur[s];i != -1;i = e[i].next) { cur[s] = i; if(deep[e[i].to] != deep[s] + 1) continue; int f = dfs(e[i].to,t,min(limit,e[i].v)); if(f) { e[i].v -= f,e[i^1].v += f; limit -= f,flow += f; if(!limit) break; } } if(!flow) deep[s] = -2333333; return flow; } void dinic(int s,int t) { while(bfs(s,t)) maxflow += dfs(s,t,INF); } int main() { memset(head,-1,sizeof(head)); m = read(),n = read(); source = 0,sink = n+1; while(1) { x = read(),y = read(); if(x == -1 && y == -1) break; add(x,y,1),add(y,x,0),sum++; } rep(i,1,m) add(source,i,1),add(i,source,0); rep(i,m+1,n) add(i,sink,1),add(sink,i,0); dinic(source,sink); if(maxflow) { printf("%d\n",maxflow); for(int i = 0;i <= (sum-1)<<1;i += 2) if(e[i^1].v != 0) printf("%d %d\n",e[i].from,e[i].to); } else printf("No Solution!\n"); return 0; }
当你意识到,每个上一秒都成为永恒。