标签:
题意:
二分图最大匹配
思路:
二分图最大匹配基础算法就是匈牙利算法,和网络流中的找增广路很类似
个人偏好DFS版本= =
当时也是看kuangbin大大的模板才逐渐摸索的
补充定义和定理:
最大匹配数:最大匹配的匹配边的数目
最小点覆盖数:选取最少的点,使任意一条边至少有一个端点被选择
最大独立数:选取最多的点,使任意所选两点均不相连
最小路径覆盖数:对于一个 DAG(有向无环图),选取最少条路径,使得每个顶点属于且仅属于一条路径。路径长可以为 0(即单个点)。
定理1:最大匹配数 = 最小点覆盖数(这是 Konig 定理)
定理2:最大匹配数 = 最大独立数
定理3:最小路径覆盖数 = 顶点数 - 最大匹配数
注意,无向图最大匹配数要除以2,因为是无向图!
附上代码:
#include <iostream> #include <stdio.h> #include <algorithm> #include <string.h> #include <string> #include <math.h> #include <stack> #include <queue> #include <vector> #include <map> #include <set> #pragma warning(disable:4996) #define Zero(a) memset(a, 0, sizeof(a)) #define Neg(a) memset(a, -1, sizeof(a)) #define All(a) a.begin(), a.end() #define PB push_back #define repf(i,a,b) for(i = a;i <= b; i++) #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define root 1,n,1 #define ld rt << 1 #define rd rt << 1 | 1 #define ll long long #define MAXN 1005 #define mod 10007 using namespace std; int linker[MAXN]; bool used[MAXN]; vector<int>mp[MAXN]; int uN; bool dfs(int u){ for (int i = 0; i<mp[u].size(); i++){ if (!used[mp[u][i]]) { used[mp[u][i]] = true; if (linker[mp[u][i]] == -1 || dfs(linker[mp[u][i]])) { linker[mp[u][i]] = u; return true; } } } return false; } int hungary() { int u; int res = 0; memset(linker, -1, sizeof(linker)); for (u = 1; u <= uN; u++) { memset(used, false, sizeof(used)); if (dfs(u)) res++; } return res; } int main(){ int k; while (~scanf("%d%d", &uN, &k)){ for (int i = 1; i <= uN; ++i){ mp[i].clear(); } int u, v; while (k--){ scanf("%d%d", &u, &v); mp[u].push_back(v); mp[v].push_back(u); } printf("%d\n%d\n", hungary() / 2, uN - hungary() / 2); } return 0; }
【hiho】hiho第三十一周·二分图最大匹配,一些基础结论也会在此更新
标签:
原文地址:http://www.cnblogs.com/mashiroG/p/4662927.html