题意:
一共有(n)个飞行员,其中有(m)个外籍飞行员和(n - m)个英国飞行员,外籍飞行员从(1)到(m)编号,英国飞行员从 (m + 1)到(n)编号。 对于给定的外籍飞行员与英国飞行员的配合情况,试设计一个算法找出最佳飞行员配对方案,使皇家空军一次能派出最多的飞机。
思路:
二分图匹配板题。用匈牙利算法输出匹配会比较方便,而且代码比较短。用网络流的话,给左右两侧的点分别连一条容量为(1)的边,建立一个超级源和超级汇点即可。
代码:
匈牙利算法:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 105;
struct Edge {
int to, nxt;
}e[maxn * maxn];
int n, m, head[maxn], numedge, match[maxn], vis[maxn], x, y, ans;
inline void AddEdge(int from, int to) {
e[numedge].to = to;
e[numedge].nxt = head[from];
head[from] = numedge;
numedge++;
}
bool dfs(int u, int tag) {
if (vis[u] == tag) return false;
vis[u] = tag;
for (int i = head[u]; ~i; i = e[i].nxt) {
int to = e[i].to;
if (!match[to] || dfs(match[to], tag)) {
match[to] = u;
return true;
}
}
return false;
}
int main() {
memset(head, -1, sizeof(head));
scanf("%d%d", &m, &n);
while (scanf("%d%d", &x, &y)) {
if (x == -1 && y == -1) break;
AddEdge(x, y);
}
for (int i = 1; i <= m; i++) {
if (dfs(i, i)) ans++;
}
printf("%d
", ans);
for (int i = m + 1; i <= n; i++)
if (match[i]) {
printf("%d %d
", match[i], i);
}
return 0;
}
Dinic算法:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#define root 0
#define target 104
using namespace std;
const int maxn = 105;
const int INF = 0x3f3f3f3f;
struct Edge {
int to, val, nxt;
}e[maxn * maxn * 2];
int numedge, head[maxn], ans, n, m, x, y, depth[maxn];
inline void AddEdge(int from, int to, int val) {
e[numedge].to = to;
e[numedge].val = val;
e[numedge].nxt = head[from];
head[from] = numedge;
numedge++;
}
bool bfs() {
memset(depth, 0, sizeof(depth));
depth[root] = 1;
queue<int> q;
q.push(root);
while (!q.empty()) {
int u = q.front();
q.pop();
for (int i = head[u]; ~i; i = e[i].nxt) {
int to = e[i].to;
if (e[i].val > 0 && !depth[to]) {
depth[to] = depth[u] + 1;
q.push(to);
}
}
}
return depth[target] != 0;
}
int dfs(int u, int flow) {
if (u == target) return flow;
for (int i = head[u]; ~i; i = e[i].nxt) {
int to = e[i].to;
if (e[i].val > 0 && depth[to] > depth[u]) {
int di = dfs(to, min(flow, e[i].val));
if (di > 0) {
e[i].val -= di;
e[i ^ 1].val += di;
return di;
}
}
}
return 0;
}
inline void Dinic() {
ans = 0;
while (bfs()) {
int d;
while (d = dfs(root, INF)) {
ans += d;
}
}
}
int main() {
memset(head, -1, sizeof(head));
scanf("%d%d", &m, &n);
while (scanf("%d%d", &x, &y)) {
if (x == -1 && y == -1) break;
AddEdge(x, y, 1);
AddEdge(y, x, 0);
}
for (int i = 1; i <= m; i++) {
AddEdge(root, i, 1);
AddEdge(i, root, 0);
}
for (int i = m + 1; i <= n; i++) {
AddEdge(i, target, 1);
AddEdge(target, i, 0);
}
Dinic();
printf("%d
", ans);
for (int i = 1; i <= m; i++) {
for (int j = head[i]; ~j; j = e[j].nxt) {
int to = e[j].to;
if (to == root) continue;
if (!e[j].val) {
printf("%d %d
", i, to);
break;
}
}
}
return 0;
}