参考: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(); }
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
http://blog.csdn.net/Rappy/article/details/1790647
5. 二分图多重匹配 例如POJ3189
http://blog.chinaunix.net/space.php?uid=23709303&do=blog&id=2388865