二分图板子
Posted vikyanite
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二分图板子相关的知识,希望对你有一定的参考价值。
二分图最大匹配:
匈牙利算法 邻接表O(mn):
#pragma GCC optimize(2) #include <bits/stdc++.h> using namespace std; const int maxn = 1010; const int maxm = 2e5; int n, m, t; int mch[maxn], vistime[maxn]; struct E { int to, next; }edge[maxm]; int tot, head[maxn]; void init() { memset(vistime, 0, sizeof(vistime)); memset(head, -1, sizeof(head)); tot = 0; } inline void add_edge(int u, int v) { edge[tot].to = v; edge[tot].next = head[u]; head[u] = tot++; } bool Hungarian(int u, int tag) { if (vistime[u] == tag) return 0; vistime[u] = tag; for (int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; if ((mch[v] == 0) || Hungarian(mch[v], tag)) { mch[v] = u; return 1; } } return 0; } int main() { scanf("%d%d%d", &n, &m, &t); init(); while (t--) { int u, v; scanf("%d%d", &u, &v); add_edge(u, v); } int ans = 0; for (int i = 1; i <= n; ++ i) if (Hungarian(i, i)) ++ans; printf("%d ", ans); return 0; }
KM算法 O(N^3):
#include <bits/stdc++.h> using namespace std; const int maxn = 501; const int maxm = 250001; const int inf = 0x3f3f3f3f; int nl, nr, m; int tot, head[maxn]; int ans, linkx[maxn], linky[maxn]; int dx[maxn], dy[maxn]; struct E { int to, next; }edge[maxm]; //这里千万要注意,如果题目是双向边的话,这里的N要开2*N inline void read(int& ans) { int x = 0, f = 1; char ch = getchar(); while (ch<‘0‘ || ch > ‘9‘) { if (ch == ‘-‘) f = -1; ch = getchar(); } while ( ch >= ‘0‘ && ch <= ‘9‘) { x = x * 10 + ch - ‘0‘; ch = getchar(); } ans = x * f; } //加边 inline void add_edge(int u, int v) { edge[tot].to = v; edge[tot].next = head[u]; head[u] = tot++; if (!linkx[u] && !linky[v]) linky[v] = u, linkx[u] = v, ++ ans; } bool bfs() { bool ret=0; queue<int> q; memset(dx, 0, sizeof(dx)), memset(dy, 0, sizeof(dy)); for (int i = 1; i <= nl; ++ i) if (!linkx[i]) q.push(i); while (!q.empty()) { int u = q.front(); q.pop(); for (int i = head[u]; ~i; i = edge[i].next) { int v = edge[i].to; if (!dy[v]) { dy[v] = dx[u] + 1; if (!linky[v]) ret = 1; else dx[linky[v]] = dy[v]+1, q.push(linky[v]); } } } return ret; } bool dfs(int u) { for (int i = head[u]; ~i; i = edge[i].next) { int v = edge[i].to; if (dy[v] == dx[u] + 1) { dy[v] = 0; if (!linky[v] || dfs(linky[v])) { linky[v] = u, linkx[u] = v; return 1; } } } return 0; } int main() { int a, b; memset(head, -1, sizeof(head)); read(nl), read(nr), read(m); for (int i = 1; i <= m; ++ i) read(a), read(b), add_edge(a,b); while(bfs()) { for (int i = 1; i <= nl; ++ i) if (!linkx[i] && dfs(i)) ++ ans; } printf("%d ",ans); // 这段循环是用来输出跟谁匹配 // for (int i = 1; i <= nl; ++ i) // printf("%d ",linkx[i]); return 0; }
以上是关于二分图板子的主要内容,如果未能解决你的问题,请参考以下文章
创建广告时出现代码 200 和子代码 1487194 的 Facebook 错误背后的原因是啥?
在 SpriteKit 中出现错误。 - 线程 1:EXC_BREAKPOINT(代码=1,子代码=0x1007351fc)
Facebook OAuthException代码190子代码490 - 用户注册了阻塞的登录检查点
斯威夫特 3 - 'EXC_BAD_INSTRUCTION(代码 = EXC_1386_INVOP,子代码 = 0x0)' 错误