洛谷P2756 飞行员配对方案问题 题解

Problem

题目描述

英国皇家空军从沦陷国征募了大量外籍飞行员。由皇家空军派出的每一架飞机都需要配备在航行技能和语言上能互相配合的 2 名飞行员,其中 1 名是英国飞行员,另 1 名是外籍飞行员。在众多的飞行员中,每一名外籍飞行员都可以与其他若干名英国飞行员很好地配合。如何选择配对飞行的飞行员才能使一次派出最多的飞机。对于给定的外籍飞行员与英国飞行员的配合情况,试设计一个算法找出最佳飞行员配对方案,使皇家空军一次能派出最多的飞机。

对于给定的外籍飞行员与英国飞行员的配合情况,编程找出一个最佳飞行员配对方案,使皇家空军一次能派出最多的飞机。

输入输出格式

输入格式:

第 1 行有 2 个正整数$m$和$n$。$n$是皇家空军的飞行员总数$(n<100)$;$m$是外籍飞行员数$(m<=n)$。外籍飞行员编号为$1$ ~ $m$;英国飞行员编号为$m+1$ ~ $n$。

接下来每行有 2 个正整数$i$和$j$,表示外籍飞行员$i$可以和英国飞行员$j$配合。最后以2个-1结束。

输出格式:

第 1 行是最佳飞行员配对方案一次能派出的最多的飞机数$M$。接下来$M$行是最佳飞行员配对方案。每行有 2个正整数$i$和$j$,表示在最佳飞行员配对方案中,飞行员$i$和飞行员$j$配对。如果所求的最佳飞行员配对方案不存在,则输出‘No Solution!’。

输入输出样例

1
2
3
4
5
6
7
8
9
10
11
12
13
Input #1
5 10
1 7
1 8
2 6
2 9
2 10
3 7
3 8
4 7
4 8
5 10
-1 -1
1
2
3
4
5
6
Output #1
4
1 7
2 9
3 8
5 10

Solution

虽然是网络流的经典题,但由于我这个蒟蒻不会网络流,用匈牙利算法水过了。

乍一看,二分图匹配板子题,板子拉下来稍微改一下。

就这么过了

P.S.: 匈牙利算法模板可以参考这篇题解,里面写的还是很不错的。

模板题唯一的不同之处在于,它要求输出配对方案。

由于我们在计算方案数的时候已经将match数组对应好了,最后无脑输出就可以了。

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
#include <bits/stdc++.h>
using namespace std;

const int MAXN = 100 + 5;
struct node
{
int from, to, next;
}edge[MAXN * MAXN];
int cnt, ans;
int m, n, e;
int a, b;
int head[MAXN], lastt[MAXN], match[MAXN];

void add(int a, int b)
{
edge[++cnt].from = a;
edge[cnt].to = b;
edge[cnt].next = head[a];
head[a] = cnt;
}

int iter(int p, int t)
{
for(int i = head[p]; i; i = edge[i].next)
{
int to = edge[i].to;
if (lastt[to] != t)
{
lastt[to] = t;
if (!match[to] || iter(match[to], t)) { match[to] = p; return true; }
}
}
return false;
}

int main()
{
cin >> m >> n;
while(true)
{
cin >> a >> b;
if (a == -1 && b == -1) break;
add(a, b);
}
for (int i = 1; i <= m; i++)
if (iter(i, i)) ans++;
cout << ans << endl;
for (int i = m + 1; i <= n; i++) if (match[i]) cout << match[i] << ' ' << i << endl;
return 0;
}

Data

提交请至洛谷P2756