原题链接

题目大意

总共有飞行员n个,其中外籍飞行员有m个,外籍飞行员可与数个英国飞行员配对,给出每个外籍飞行员的配对情况,求最大匹配数并输出方案。

解题思路

二分图最大匹配模板题,图建好直接跑网络流求最大流。

AC代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<cstring>
#define MAX_V 1000
using namespace std;

const int INF = (unsigned int)(-1)>>1;
struct edge {
int to,cap,rev;
};

vector<edge> G[MAX_V]; //图的邻接表表示
int level[MAX_V]; //结点到源点的距离标号
int iter[MAX_V]; //当前弧,在其之前的边已经没有用了

//向图中增加一条从from到to的容量为cap(剩余流量)的边
void add_edge(int from,int to,int cap) {
G[from].push_back((edge) {
to,cap,G[to].size()
});
G[to].push_back((edge) {
from,0,G[from].size()-1
});
}

//通过BFS计算从源点出发的距离标号
void bfs(int s) {
memset(level,-1,sizeof(level));

queue<int> que;

level[s]=0;

que.push(s);

while(!que.empty()) {
int v = que.front();
que.pop();

for(int i=0; i<G[v].size(); i++) {
edge &e = G[v][i];

if(e.cap > 0 && level[e.to]<0) {
level[e.to] = level[v] +1;
que.push(e.to);
}
}
}
}

//通过DFS寻找增广路
int dfs(int v,int t,int f) {
if(v == t)return f;

for(int &i=iter[v]; i<G[v].size(); i++) {
edge &e = G[v][i];
if(e.cap > 0 && level[v] < level[e.to]) {
int d =dfs(e.to,t,min(f,e.cap));

if(d>0) {
e.cap -= d;

G[e.to][e.rev].cap += d;

return d;
}
}
}

return 0;
}

//求解从s到t的最大流

int max_flow(int s, int t) {
int flow = 0;

for(;;) {
bfs(s);

if(level[t]<0)return flow;
memset(iter,0,sizeof(iter));

int f;

while((f= dfs(s,t,INF))>0) {
flow += f;
}
}
}
int n,m;
int main()
{
cin>>m>>n;
int s=0,t=n+1;
int a,b;
for(int i=1;i<=m;i++)
{
add_edge(s,i,1);
}
for(int i=m+1;i<=n;i++)
{
add_edge(i,t,1);
}
while(cin>>a>>b)
{
if(a==-1&&b==-1)break;
add_edge(a,b,1);
}

int ans = max_flow(s,t);
cout<<ans<<endl;
if(ans==0)cout<<"No Solution!";
else{
for(int i=1;i<=m;++i){
for(int j=0;j<G[i].size();++j){
edge &e = G[i][j];
if(e.cap==0&&e.to>m&&e.to<=n){
cout<<i<<" "<<e.to<<endl;
break;
}
}
}
}
return 0;
}