参考:http://kukumayas.iteye.com/blog/1075610
http://chhaj5236.blog.163.com/blog/static/1128810812009910102617216/
1. 匈牙利算法DFS实现 O(VE)
#include <iostream>
using namespace std;
const int N = 1000;
int nx, ny;
int g[N][N];
int mx[N], my[N];
bool chk[N];
bool searchPath(int u)
{
int v;
for(v = 0; v < ny; v++)
{
if(g[u][v] && !chk[v])
{
chk[v] = true;
if(my[v] == -1 || searchPath(my[v]))
{
my[v] = u;
mx[u] = v;
return true;
}
}
}
return false;
}
int maxMatch()
{
int u, ret = 0;
memset(mx, -1, sizeof(mx));
memset(my, -1, sizeof(my));
for(u = 0; u < nx; u++)
{
if(mx[u] == -1)
{
memset(chk, false, sizeof(chk));
if(searchPath(u))
{
ret++;
}
}
}
return ret;
}
void input()
{
for(int i = 0; i < N; i++)
{
for(int j = 0; j < N; j++)
{
g[i][j] = 0;
}
}
cin >> nx >> ny;
for(int i = 0; i < nx; i++)
{
int n, y;
cin >> n;
for(int j = 0; j < n; j++)
{
cin >> y;
g[i][y] = 1;
}
}
for(int i = 0; i < nx; i++)
{
for(int j = 0; j < ny; j++)
{
cout << g[i][j] << " ";
}
cout << endl;
}
cout << endl;
}
void display()
{
for(int i = 0; i < nx; i++)
{
cout << mx[i] << " ";
}
cout << endl;
for(int i = 0; i < ny; i++)
{
cout << my[i] << " ";
}
cout << endl;
}
int main()
{
input();
int m = maxMatch();
cout << "max match is " << m << endl;
display();
}
2. 匈牙利算法BFS实现 O(VE)
#include <iostream>
using namespace std;
const int N = 1000;
int nx, ny;
int g[N][N];
int mx[N], my[N];
int chk[N];
int Q[N];
int pre[N];
int maxMatch()
{
int res = 0;
int qs, qe;
memset(mx, -1, sizeof(mx));
memset(my, -1, sizeof(my));
memset(chk, -1, sizeof(chk));
for(int i = 0; i < nx; i++)
{
if(mx[i] == -1)
{
qs=qe=0;
Q[qe++] = i;
pre[i]=-1;
bool flag = 0;
while(qs < qe && !flag)
{
int u = Q[qs];
for(int v = 0; v < ny && !flag; v++)
{
if(g[u][v] && chk[v] != i)
{
chk[v] = i;
Q[qe++] = my[v];
if(my[v] >=0)
{
pre[my[v]] = u;
}
else
{
flag = 1;
int d = u, e = v;
while(d!=-1)
{
int t = mx[d];
mx[d] = e;
my[e] = d;
d=pre[d];
e = t;
}
}
}
}
qs++;
}
if(mx[i] != -1)
{
res++;
}
}
}
return res;
}
void input()
{
for(int i = 0; i < N; i++)
{
for(int j = 0; j < N; j++)
{
g[i][j] = 0;
}
}
cin >> nx >> ny;
for(int i = 0; i < nx; i++)
{
int n, y;
cin >> n;
for(int j = 0; j < n; j++)
{
cin >> y;
g[i][y] = 1;
}
}
for(int i = 0; i < nx; i++)
{
for(int j = 0; j < ny; j++)
{
cout << g[i][j] << " ";
}
cout << endl;
}
cout << endl;
}
void display()
{
for(int i = 0; i < nx; i++)
{
cout << mx[i] << " ";
}
cout << endl;
for(int i = 0; i < ny; i++)
{
cout << my[i] << " ";
}
cout << endl;
}
int main()
{
input();
int m = maxMatch();
cout << "max match is " << m << endl;
display();
}
3. Hopcroft-Carp算法 O(V^0.5 * E)
http://hi.baidu.com/czyuan_acm/blog/item/cd482e35d3947e1890ef3919.html
该算法的精髓在于同时找多条增广路进行反转。我们先用BFS找出可能的增广路,这里用到BFS层次搜索的概念,记录当前结点在第几层,用于后面DFS沿增广路反转时用,然后再用DFS沿每条增广路反转。这样不停地找,直至无法找到增广路为止。
#include <iostream>
#include <queue>
using namespace std;
const int N = 1000;
const int INF = 1<<28;
int nx, ny;
int g[N][N];
int mx[N], my[N];
int dx[N], dy[N], dis;
bool vst[N];
bool searchPath()
{
queue<int> q;
dis = INF;
memset(dx, -1, sizeof(dx));
memset(dy, -1, sizeof(dy));
for(int i = 0; i < nx; 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;
}
for(int v = 0; v < ny; v++)
{
if(g[u][v] && 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)
{
for(int v=0; v < ny; v++)
{
if(!vst[v] && g[u][v] && (dy[v] == dx[u] +1))
{
vst[v]=1;
if(my[v]!=-1 && dy[v] == dis)
{
continue;
}
if(my[v] == -1 || DFS(my[v]))
{
my[v] = u;
mx[u] = v;
return 1;
}
}
}
return 0;
}
int maxMatch()
{
int res = 0;
memset(mx, -1, sizeof(mx));
memset(my, -1, sizeof(my));
while(searchPath())
{
memset(vst, 0, sizeof(vst));
for(int i = 0; i < nx; i++)
{
if(mx[i] == -1 && DFS(i))
{
res++;
}
}
}
return res;
}
void input()
{
for(int i = 0; i < N; i++)
{
for(int j = 0; j < N; j++)
{
g[i][j] = 0;
}
}
cin >> nx >> ny;
for(int i = 0; i < nx; i++)
{
int n, y;
cin >> n;
for(int j = 0; j < n; j++)
{
cin >> y;
g[i][y] = 1;
}
}
for(int i = 0; i < nx; i++)
{
for(int j = 0; j < ny; j++)
{
cout << g[i][j] << " ";
}
cout << endl;
}
cout << endl;
}
void display()
{
for(int i = 0; i < nx; i++)
{
cout << mx[i] << " ";
}
cout << endl;
for(int i = 0; i < ny; i++)
{
cout << my[i] << " ";
}
cout << endl;
}
int main()
{
input();
int m = maxMatch();
cout << "max match is " << m << endl;
display();
}
测试如下,
/home/a/j/nomad2:cat input
4 4
2 1 3
3 0 1 2
1 1
2 2 3
/home/a/j/nomad2:cat input|./a.out
0 1 0 1
1 1 1 0
0 1 0 0
0 0 1 1
max match is 4
3 0 1 2
1 2 3 0
4. 二分图的最佳匹配(KM 算法)
http://blog.csdn.net/Rappy/article/details/1790647
5. 二分图多重匹配 例如POJ3189
http://blog.chinaunix.net/space.php?uid=23709303&do=blog&id=2388865