hungary HK 多重匹配
1 /*Author :usedrose */ 2 /*Created Time :2015/8/1 23:39:01*/ 3 /*File Name :2.cpp*/ 4 #pragma comment(linker, "/STACK:1024000000,1024000000") 5 #include <cstdio> 6 #include <iostream> 7 #include <algorithm> 8 #include <sstream> 9 #include <cstdlib> 10 #include <cstring> 11 #include <climits> 12 #include <vector> 13 #include <string> 14 #include <ctime> 15 #include <cmath> 16 #include <deque> 17 #include <queue> 18 #include <stack> 19 #include <set> 20 #include <map> 21 #define INF 0x3f3f3f3f 22 #define eps 1e-8 23 #define pi acos(-1.0) 24 #define MAXN 5010 25 #define MAXM 50010 26 #define OK cout << "ok" << endl; 27 #define o(a) cout << #a << " = " << a << endl 28 #define o1(a,b) cout << #a << " = " << a << " " << #b << " = " << b << endl 29 using namespace std; 30 typedef long long LL; 31 32 struct Edge{ 33 int to, next; 34 }edge[MAXM]; 35 int head[MAXM], tot; 36 37 void init() 38 { 39 tot = 0; 40 memset(head, -1, sizeof(head)); 41 } 42 43 void addedge(int u, int v) 44 { 45 edge[tot].to = v; 46 edge[tot].next = head[u]; 47 head[u] = tot++; 48 } 49 50 int linker[MAXN]; 51 bool used[MAXN]; 52 int uN; 53 54 bool dfs(int u) 55 { 56 for (int i = head[u]; i != -1; i = edge[i].next) { 57 int v = edge[i].to; 58 if (!used[v]) { 59 used[v] = true; 60 if (linker[v] == -1 || dfs(linker[v])) { 61 linker[v] = u; 62 return true; 63 } 64 } 65 } 66 return false; 67 } 68 69 int hungary() 70 { 71 int res = 0; 72 memset(linker, -1, sizeof(linker)); 73 for (int u = 0;u < uN;++ u) { 74 memset(used, false, sizeof(used)); 75 if (dfs(u)) res++; 76 } 77 return res; 78 } 79 80 81 int main() 82 { 83 while (~scanf("%d", &uN)) { 84 init(); 85 int a, b, c; 86 for (int i = 0;i < uN; ++ i) { 87 scanf("%d: (%d)", &a, &b); 88 for (int j = 0;j < b; ++ j) { 89 scanf("%d", &c); 90 addedge(a, c); 91 } 92 } 93 printf("%d\n", uN - hungary()/2); 94 } 95 return 0; 96 }
HK模板
1 /*Author :usedrose */ 2 /*Created Time :2015/8/3 14:55:13*/ 3 /*File Name :2.cpp*/ 4 #pragma comment(linker, "/STACK:1024000000,1024000000") 5 #include <cstdio> 6 #include <iostream> 7 #include <algorithm> 8 #include <sstream> 9 #include <cstdlib> 10 #include <cstring> 11 #include <climits> 12 #include <vector> 13 #include <string> 14 #include <ctime> 15 #include <cmath> 16 #include <deque> 17 #include <queue> 18 #include <stack> 19 #include <set> 20 #include <map> 21 #define INF 0x3f3f3f3f 22 #define eps 1e-8 23 #define pi acos(-1.0) 24 #define MAXN 3010 25 #define MAXM 100110 26 #define OK cout << "ok" << endl; 27 #define o(a) cout << #a << " = " << a << endl 28 #define o1(a,b) cout << #a << " = " << a << " " << #b << " = " << b << endl 29 using namespace std; 30 typedef long long LL; 31 32 33 vector<int> G[MAXN]; 34 int uN; 35 int Mx[MAXN], My[MAXN]; 36 int dx[MAXN], dy[MAXN]; 37 int dis; 38 bool used[MAXN]; 39 40 bool SearchP() 41 { 42 queue<int> Q; 43 dis = INF; 44 memset(dx, -1, sizeof(dx)); 45 memset(dy, -1, sizeof(dy)); 46 for (int i = 0;i < uN; ++ i) 47 if (Mx[i] == -1) { 48 Q.push(i); 49 dx[i] = 0; 50 } 51 while (!Q.empty()) { 52 int u = Q.front(); 53 Q.pop(); 54 if (dx[u] > dis) break; 55 int sz = G[u].size(); 56 for (int i = 0;i < sz; ++ i) { 57 int v = G[u][i]; 58 if (dy[v] == -1) { 59 dy[v] = dx[u] + 1; 60 if (My[v] == -1) dis = dy[v]; 61 else { 62 dx[My[v]] = dy[v] + 1; 63 Q.push(My[v]); 64 } 65 } 66 } 67 } 68 return dis != INF; 69 } 70 71 bool DFS(int u) 72 { 73 int sz = G[u].size(); 74 for (int i = 0;i < sz; ++ i) { 75 int v = G[u][i]; 76 if (!used[v] && dy[v] == dx[u] + 1) { 77 used[v] = true; 78 if (My[v] != -1 && dy[v] == dis) continue; 79 if (My[v] == -1 || DFS(My[v])) { 80 My[v] = u; 81 Mx[u] = v; 82 return true; 83 } 84 } 85 } 86 return false; 87 } 88 89 int MaxMatch() 90 { 91 int res = 0; 92 memset(Mx, -1, sizeof(Mx)); 93 memset(My, -1, sizeof(My)); 94 while (SearchP()) { 95 memset(used, false, sizeof(used)); 96 for (int i = 0;i < uN; ++ i) 97 if (Mx[i] == -1 && DFS(i)) 98 res++; 99 } 100 return res; 101 } 102 103 int T, k; 104 int t, n, m; 105 int x[MAXN], y[MAXN], s[MAXN]; 106 107 int main() 108 { 109 //freopen("data.in","r",stdin); 110 //freopen("data.out","w",stdout); 111 cin.tie(0); 112 ios::sync_with_stdio(false); 113 cin >> T; 114 while (T--) { 115 cin >> t; 116 cin >> m; 117 for (int i = 0;i < m; ++ i) 118 cin >> x[i] >> y[i] >> s[i]; 119 cin >> uN; 120 for (int i = 0;i <= uN; ++ i) { 121 G[i].clear(); 122 } 123 int a, b; 124 for (int i = 0;i < uN; ++ i) { 125 cin >> a >> b; 126 for (int j = 0;j < m; ++ j) { 127 if (sqrt((a-x[j])*(a-x[j]) + (b-y[j])*(b-y[j])) <= t*s[j]) { 128 //G[j].push_back(i); 129 G[i].push_back(j); 130 } 131 } 132 } 133 cout << "Scenario #" << ++k << ":" << endl; 134 cout << MaxMatch() << endl << endl; 135 } 136 return 0; 137 }
多重匹配模板
hdu 3605
http://www.cppblog.com/JulyRina/archive/2015/02/13/209816.html
题目大意:有N(N<100,000)个人要去M(M<10)个星球,每个人只可以去一些星球,一个星球最多容纳Ki个人。请问是否所有人都可以选择自己的星球
题目分析;直接建立二分图模型,使用匈牙利算法。
匈牙利算法可以解决多重匹配,原理和二分图最大匹配很像。注意不要把可以匹配多个的点分割然后按照正常的二分匹配来做,那样肯定会挂的。
解决多重匹配就是记录一下多重匹配的点(简称Y方点)已经匹配了Pi个点。如果Pi<Ki那么就直接上了,否则的话继续搜索Yi已经匹配的每一个点并将Yi染色。
因为Yi搜一次就需要染色了,而且Y方点最多是10个,所以每次找增广路的深度最多是10,这样就很快了。
1 /*Author :usedrose */ 2 /*Created Time :2015/8/3 18:48:30*/ 3 /*File Name :2.cpp*/ 4 #pragma comment(linker, "/STACK:1024000000,1024000000") 5 #include <cstdio> 6 #include <iostream> 7 #include <algorithm> 8 #include <sstream> 9 #include <cstdlib> 10 #include <cstring> 11 #include <climits> 12 #include <vector> 13 #include <string> 14 #include <ctime> 15 #include <cmath> 16 #include <deque> 17 #include <queue> 18 #include <stack> 19 #include <set> 20 #include <map> 21 #define INF 0x3f3f3f3f 22 #define eps 1e-8 23 #define pi acos(-1.0) 24 #define MAXN 100010 25 #define MAXM 11 26 #define OK cout << "ok" << endl; 27 #define o(a) cout << #a << " = " << a << endl 28 #define o1(a,b) cout << #a << " = " << a << " " << #b << " = " << b << endl 29 using namespace std; 30 typedef long long LL; 31 32 int n, m; 33 int stk[MAXM][MAXN], top[MAXM], Maxpeo[MAXM]; 34 bool G[MAXN][MAXM]; 35 bool T[MAXM]; 36 37 //适用于正整数 38 template <class T> 39 inline void scan_d(T &ret) { 40 char c; ret=0; 41 while((c=getchar())<'0'||c>'9'); 42 while(c>='0'&&c<='9') ret=ret*10+(c-'0'),c=getchar(); 43 } 44 45 bool dfs(int u) 46 { 47 for (int i = 1;i <= m; ++ i) 48 if (G[u][i] && !T[i]) { 49 T[i] = true; 50 if (top[i] < Maxpeo[i]) {//如果该星球未注满 直接匹配 51 stk[i][top[i]++] = u; 52 return true; 53 } 54 for (int j = 0;j < top[i]; ++ j) //否则 55 if (dfs(stk[i][j])) { //将已经匹配的点寻找其他可行匹配 56 stk[i][j] = u; 57 return true; 58 } 59 } 60 return false; 61 } 62 63 bool solve() 64 { 65 memset(top, 0, sizeof(top)); 66 for (int i = 1;i <= n; ++ i) { 67 memset(T, 0, sizeof(T)); 68 if (!dfs(i)) return false; 69 } 70 return true; 71 } 72 73 void input() 74 { 75 for (int i = 1;i <= n; ++ i) 76 for (int j = 1;j <= m; ++ j) 77 scan_d(G[i][j]); 78 for (int i = 1;i <= m; ++ i) 79 scan_d(Maxpeo[i]); 80 } 81 82 int main() 83 { 84 while (~scanf("%d%d", &n, &m)) { 85 input(); 86 if (solve()) puts("YES"); 87 else puts("NO"); 88 } 89 return 0; 90 }