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
", uN - hungary()/2);
94     }
95     return 0;
96 }
View Code

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 }
View Code

多重匹配模板

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 }
View Code
原文地址:https://www.cnblogs.com/usedrosee/p/4694940.html