参考两篇比较好的博客
http://www.renfei.org/blog/bipartite-matching.html
http://blog.csdn.net/thundermrbird/article/details/52231639###;
最大匹配数为n 2*n个不同的点 n条不同的边
匈牙利算法
从未匹配的的点出发寻找 非匹配边大于匹配边的交替路(增广路)匹配边与非匹配边交换
匈牙利算法模板(DFS,邻接矩阵版) 时间复杂度O(V*E)
1 #include <stdio.h> 2 #include <math.h> 3 #include <string.h> 4 #include <stdlib.h> 5 #include <iostream> 6 #include <sstream> 7 #include <algorithm> 8 #include <string> 9 #include <queue> 10 #include <map> 11 #include <vector> 12 using namespace std; 13 const int maxn = 1005; 14 const int maxm = 1e4+10; 15 const int inf = 0x3f3f3f3f; 16 const double epx = 1e-10; 17 typedef long long ll; 18 int n,m,k; 19 int visit[maxn]; 20 int match[maxn]; 21 int a[maxn][maxn]; 22 bool found(int x) 23 { 24 for(int i=1;i<=m;i++) //从右边的集合中找能与x进行匹配的点 25 { 26 if(a[x][i]==1&&visit[i]==0) //x与i有联系且i没被查找过 27 { 28 visit[i]=1; 29 if(match[i]==0||found(match[i])) //第i个点还没有匹配 如果匹配了就看 与它匹配的那个点 能不能换个点完成匹配 把i空出来 如果可以i与x匹配 30 { 31 match[i]=x; 32 return true; 33 } 34 } 35 } 36 return false; 37 } 38 int main() 39 { 40 while(scanf("%d",&k)!=EOF&&k) //k条边 41 { 42 scanf("%d%d",&n,&m); //左右两个集合的数量 43 memset(a,0,sizeof(a)); 44 for(int i=1;i<=k;i++) 45 { 46 int x,y; 47 scanf("%d %d",&x,&y); 48 a[x][y]=1; //有联系的点标记为1 49 } 50 memset(match,0,sizeof(match)); 51 int ans=0; 52 for(int i=1;i<=n;i++) //依次对左边集合中点进行匹配 53 { 54 memset(visit,0,sizeof(visit)); //清空访问标记数组 55 if(found(i)) //满足条件匹配数+1 56 ans++; 57 } 58 printf("%d ",ans); 59 } 60 }
Hopcroft-Karp 算法
复杂度 O(sqrt(n)*E)
邻接表存图,vector 实现 ,vector 先初始化,然后加入边 , uN 为左端的顶点数,使用前赋值 (点编号 0 开始)
#include <bits/stdc++.h> #define pb push_back #define mp make_pair #define fi first #define se second #define all(a) (a).begin(), (a).end() #define fillchar(a, x) memset(a, x, sizeof(a)) #define huan printf(" ") #define debug(a,b) cout<<a<<" "<<b<<" "<<endl #define ffread(a) fastIO::read(a) using namespace std; typedef long long ll; typedef pair<int,int> pii; const int MAXN = 1000+5; const int INF = 0x3f3f3f3f; vector<int>G[MAXN]; int uN; int Mx[MAXN],My[MAXN]; int dx[MAXN],dy[MAXN]; int dis; bool used[MAXN]; void init(int n) { uN=n; for(int i=0; i<n; i++) G[i].clear(); } bool SearchP() { queue<int>Q; dis = INF; memset(dx,-1,sizeof(dx)); memset(dy,-1,sizeof(dy)); for(int i = 0 ; i < uN; i++) if(Mx[i]==-1) { Q.push(i); dx[i] = 0; } while(!Q.empty()) { int u = Q.front(); Q.pop(); if(dx[u] > dis) break; int sz = G[u].size(); for(int i = 0; i < sz; i++) { int v = G[u][i]; if(dy[v]==-1) { dy[v] = dx[u] + 1; if(My[v] == -1) dis = dy[v]; else { dx[My[v]] = dy[v] + 1; Q.push(My[v]); } } } } return dis != INF; } bool DFS(int u) { int sz = G[u].size(); for(int i = 0; i < sz; i++) { int v = G[u][i]; if(!used[v] && dy[v] == dx[u] + 1) { used[v] = true; if(My[v] != -1 && dy[v] == dis) continue; if(My[v] == -1 || DFS(My[v])) { My[v] = u; Mx[u] = v; return true; } } } return false; } int MaxMatch() { int res = 0; memset(Mx,-1,sizeof(Mx)); memset(My,-1,sizeof(My)); while(SearchP()) { memset(used,false,sizeof(used)); for(int i = 0; i < uN; i++) if(Mx[i] == -1 && DFS(i)) res++; } return res; } int main() { int n,m,k; while(scanf("%d",&k)&&k) { scanf("%d%d",&m,&n); init(m); for(int i=0; i<k; i++) { int x,y; scanf("%d%d",&x,&y); G[x-1].pb(y-1); } printf("%d ",MaxMatch()); } }