P2071 座位安排(二分图匹配)
思路:虽然是典型的二分图匹配题型,出现在网络流的提单中,也不是没有原因的。
因为二分图匹配的题型都能套网络流的板子,但是如果你既懒得敲模板也懒得复制粘贴(比如说我~)
,就可以用匈牙利算法,非常简单,也非常好理解,就是如果匹配的位置空着就直接占用,
或者就让之前占用位置的人去找另一个他想要的位置,如果他找到了,自己就占用他刚才占用的位置。
应该是说清楚了的吧*-*
AC代码:
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 100005; const int inf = 0x3f3f3f3f; struct edge { int f, t, nxt; }e[maxn]; int hd[maxn], tot = 1; void add(int f, int t) { e[++tot] = { f,t,hd[f]}; hd[f] = tot; } int n; int match[maxn][2], vis[maxn]; bool dfs(int u) {//匈牙利 for (int i = hd[u]; i; i = e[i].nxt) { int v = e[i].t; if (vis[v])continue; vis[v] = 1; if (!match[v][0]) {//位置空着直接占用 match[v][0] = u;return true;} if (!match[v][1]) { match[v][1] = u; return true;} if (dfs(match[v][0])) {//让之前占位置的人重新找位置 match[v][0] = u; return true; } if (dfs(match[v][1])) { match[v][1] = u; return true; } } return false; } int main() { //freopen("test.txt", "r", stdin); scanf("%d", &n); for (int i = 1; i <= 2*n; i++) { int a, b; scanf("%d%d", &a, &b); add(i, a), add(i, b); } int ans = 0; for (int i = 1; i <= 2*n; i++) { memset(vis, 0, sizeof(vis)); if (dfs(i))ans++; } printf("%d\n", ans); return 0; }