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;
}

 

posted @ 2021-04-05 14:20  cono奇犽哒  阅读(61)  评论(0)    收藏  举报