[SMOJ2205]飞行员配对方案问题(二分图最大匹配)
2017-08-13 21:23
405 查看
这题是典型的二分图最大匹配问题,虽然也有专门求解这类问题的算法,但也可以直接用我们已学过的最大流解决。
题目的大意是有 m 名外籍飞行员和 (n−m) 名英国飞行员,其中每名外籍飞行员可以与若干英国飞行员配合。要求使外籍飞行员和英国飞行员一一配对驾驶一架飞机,使最终能派出的飞机数最多。
我们可以把外籍飞行员和英国飞行员抽象为两类不同的点,“能配合”的关系则是从代表外籍的点向代表英国的点连一条容量为 1 的边。例如,对于样例:
可以发现一个规律,左边的都是外籍飞行员,右边的都是英国飞行员。左边的点之间互相没有连边,右边的点之间也没有。只有从左边的点连向右边的点的边,这样的图就叫做二分图。选取其中若干边,使任意两条边都不依附于同一个顶点,要求选取尽量多的边,这样的问题就是二分图最大匹配。
不
4000
妨把“从左边的点流一个单位的流量到右边的点”视作“左边这个点的外籍飞行员与右边这个点的飞行员合作”,这就是为什么要连边的容量为 1。
那么,要使合作的对数尽可能多,当然就要求流到右边所有点的流量总和最大,而且左边每个点最多只能有一个单位流量发出(不可能同时与多人合作)。
这样的问题我们是无法直接求解的,但可以通过一个小技巧:增加超级源点 s 和超级汇点 t。从 s 向左边的点都连一条容量为 1 的边,从右边的点都向 t 连一条容量为 1 的边。现在可以认为,一条路径 s→u→v→t 表示外籍飞行员 u 与英国飞行员 v 一起开一架飞机。这样,我们从 s 点可以发出的是不超过 m 个单位的流量,经过最大流算法的匹配,最终流到 t 点的流量就是最多能配对的数量。
参考代码:
从这题中可以发现网络流的一个特征,它的题目难点在于“建模”。如何将问题的模型进行转化,从而对网络中的点、边、流赋予具体的含义,是重中之重。
因此,网络流题目的描述将不会再像之前的图论题一样,有非常明显的顶点、边的暗示,而是要靠自己去探索和发现。这就需要多加练习,掌握其中的规律。
题目的大意是有 m 名外籍飞行员和 (n−m) 名英国飞行员,其中每名外籍飞行员可以与若干英国飞行员配合。要求使外籍飞行员和英国飞行员一一配对驾驶一架飞机,使最终能派出的飞机数最多。
我们可以把外籍飞行员和英国飞行员抽象为两类不同的点,“能配合”的关系则是从代表外籍的点向代表英国的点连一条容量为 1 的边。例如,对于样例:
可以发现一个规律,左边的都是外籍飞行员,右边的都是英国飞行员。左边的点之间互相没有连边,右边的点之间也没有。只有从左边的点连向右边的点的边,这样的图就叫做二分图。选取其中若干边,使任意两条边都不依附于同一个顶点,要求选取尽量多的边,这样的问题就是二分图最大匹配。
不
4000
妨把“从左边的点流一个单位的流量到右边的点”视作“左边这个点的外籍飞行员与右边这个点的飞行员合作”,这就是为什么要连边的容量为 1。
那么,要使合作的对数尽可能多,当然就要求流到右边所有点的流量总和最大,而且左边每个点最多只能有一个单位流量发出(不可能同时与多人合作)。
这样的问题我们是无法直接求解的,但可以通过一个小技巧:增加超级源点 s 和超级汇点 t。从 s 向左边的点都连一条容量为 1 的边,从右边的点都向 t 连一条容量为 1 的边。现在可以认为,一条路径 s→u→v→t 表示外籍飞行员 u 与英国飞行员 v 一起开一架飞机。这样,我们从 s 点可以发出的是不超过 m 个单位的流量,经过最大流算法的匹配,最终流到 t 点的流量就是最多能配对的数量。
参考代码:
//prog81 #include <algorithm> #include <cstdio> #include <cstdlib> #include <cstring> #include <iostream> using namespace std; const int INF = 0x3f3f3f3f; const int MAXN = 100 + 10; struct Edge { Edge *next; int cap; int dest; // Edge () : next(NULL), cap(0), dest(0) {} } edges[MAXN * MAXN], *current, *first_edge[MAXN]; int m, n; void insert(int u, int v, int c) { current -> next = first_edge[u]; current -> cap = c; current -> dest = v; first_edge[u] = current ++; // printf("%d %d\n", u, first_edge[u]); } Edge *counterpart(Edge *x) { //求反向边,利用了正反向边在 edges 数组中是相邻储存的特性 return edges + ((x - edges) ^ 1); } bool vis[MAXN]; int dfs(int u, int f) { // printf("%d %d\n", u, f); if (u == n + 1) return f; //到达汇点,本次增广结束 if (vis[u]) return 0; else vis[u] = true; for (Edge *p = first_edge[u]; p; p = p -> next) { int v = p -> dest; if (p -> cap) if (int res = dfs(v, min(f, p -> cap))) { //找得到一条 u 到 t 的路径,流量为 res // printf("%d\n", res); p -> cap -= res; counterpart(p) -> cap += res; return res; //每次找一条 } } return 0; //无增广路 } int main(void) { freopen("2205.in", "r", stdin); freopen("2205.out", "w", stdout); scanf("%d%d", &m, &n); current = edges; fill(first_edge, first_edge + n + 1, (Edge*)0);// printf("%d %d\n", m, n); for (int i = 1; i <= m; i++) { insert(0, i, 1); insert(i, 0, 0); } //printf("%d\n", first_edge[0]); for (int i = m + 1; i <= n; i++) { insert(i, n + 1, 1); insert(n + 1, i, 0); } int i, j; while (~scanf("%d%d", &i, &j) && i > 0){ // insert(0, i, 1); insert(i, 0, 0); insert(i, j, 1); insert(j, i, 0); // insert(j, n + 1, 1); insert(n + 1, j, 0); } int ans = 0; while (true) { //不断增广,直到找不到增广路 memset(vis, false, sizeof vis); if (int res = dfs(0, INF)) ans += res; else break; } if (!ans) puts("No Solution!"); else { printf("%d\n", ans); // for (int i = 1; i <= m; i++) // for (Edge *p = first_edge[i]; p; p = p -> next) // if (!p -> cap && p -> dest) { printf("%d %d\n", i, p -> dest);/* break;*/ } } return 0; }
从这题中可以发现网络流的一个特征,它的题目难点在于“建模”。如何将问题的模型进行转化,从而对网络中的点、边、流赋予具体的含义,是重中之重。
因此,网络流题目的描述将不会再像之前的图论题一样,有非常明显的顶点、边的暗示,而是要靠自己去探索和发现。这就需要多加练习,掌握其中的规律。
相关文章推荐
- Luogu 2756 飞行员配对方案问题(二分图最大匹配)
- 飞行员配对方案问题(二分图最大匹配)
- 一、飞行员配对方案问题 [二分图的最大匹配]
- 飞行员配对方案问题(二分图的最大匹配)
- [网络流24题] 飞行员配对方案问题 最大流 二分图最大匹配
- 【学会就脱单算法】匈牙利算法之飞行员配对问题(二分图最大匹配)
- 线性规划与网络流24题の1 飞行员配对方案问题(最大匹配)
- [网络流24题] 飞行员配对方案问题 二分图/最大流
- 51nod_2006_飞行员配对(二分图最大匹配)
- 51Nod 2006 飞行员配对(二分图最大匹配) 匈牙利算法
- 二分图——洛谷P2756 飞行员配对方案问题
- 51NOD 2006 飞行员配对(二分图最大匹配)
- 线性规划与网络流24题之飞行员配对计划 二分图的最大匹配
- 51nod 基础题 飞行员配对(二分图最大匹配)
- 51nod 2006 飞行员配对(二分图最大匹配)
- 51Nod 2006:飞行员配对(二分图最大匹配,匈牙利算法)
- 51NOD-2006 飞行员配对(二分图最大匹配)
- 洛谷 P2756 飞行员配对方案问题(最大流)
- 51nod 2006 飞行员配对(二分图最大匹配)
- 网络流24题 01 飞行员配对方案问题 (多源多汇点+最大流)