http://www.renfei.org/blog/bipartite-matching.html
匈牙利算法:从左边的点出发不断地搜索,寻找增广路,交换交替路上的路径,来求解二分图的最大匹配。
模板:
bool dfs(int u) { for (int v : g[u]) { if(!vis[v]) { vis[v] = true; if(match[v] == -1 || dfs(match[v])) { match[v] = u; match[u] = v; return true; } } } return false; } int ans = 0; mem(match, -1); for (int i = 1; i <= n; ++i) { if(match[i] == -1) { mem(vis, false); if(dfs(i)) ans++; } }
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb push_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << " "; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head const int N = 2e3 + 5; int match[N]; bool vis[N]; vector<int> g[N]; int n, m, e, u, v; bool dfs(int u) { for (int v : g[u]) { if(!vis[v]) { vis[v] = true; if(match[v] == -1 || dfs(match[v])) { match[v] = u; match[u] = v; return true; } } } return false; } int main() { scanf("%d %d %d", &n, &m, &e); for (int i = 1; i <= e; ++i) { scanf("%d %d", &u, &v); if(u > n || v > m) continue; g[u].pb(v+n); g[v+n].pb(u); } int ans = 0; mem(match, -1); for (int i = 1; i <= n; ++i) { if(match[i] == -1) { mem(vis, false); if(dfs(i)) ans++; } } printf("%d ", ans); return 0; }