POJ二分图最大匹配的简单题目

 

最大匹配:1274 ,2239 ,2584(二分图多重匹配) ,2536 ,2446 
最小点覆盖(König定理,最小点覆盖数=最大匹配数):3041 ,1325 ,2226 (构图有点难度),
最小边覆盖:2724(构图比较难),3020
最大独立集(总点数-最大匹配):1466,3692
有向图最小路径覆盖:2060,1422,3216,2594(+传递闭包),1548(和3636类似,可以用Dilworth定理转化为LIS问题,也可以用匹配),
最优匹配(KM算法):3565,2195

转载:http://hi.baidu.com/lewutian/blog/item/fd9336ef0b7c2b1dfdfa3cad.html

一天不死,AC 不止!要刷这些题恐怕训练计划要延期了。。。T_T

POJ 3041 裸奔的最小点覆盖。。。建图:G[R][C+N] = true;
POJ 1274 本来可以秒掉的题,让本菜写悲剧了,忘了给图初始化,wa了两次T_T...
POJ 2239 建图G[课程th][课时th],课时 = (p - 1)*12 + q;
POJ 2584
方法一、按照最大匹配来解,建图时把每一件衣服看成衣服集合Y中的一个点,每一队员和所有的合法的衣服编号相连;建图过程见代码:      
View Code
 1 m = 0;
2 for(int i = 0; i < 5; i++) {
3 scanf("%d", num + i);
4 if(!num[i]) continue;
5 begin[i] = m;
6 m += num[i];
7 }
8
9
10 memset(g, 0, sizeof(g));
11 for(i = 0; i < n; i++) {
12 x = pos(siz[i][0]);
13 y = pos(siz[i][1]);
14 for(j = x; j <= y; j++) {
15 if(!num[j]) continue;
16 for(k = begin[j]; k < begin[j] + num[j]; k++) {
17 g[i][k] = true;
18 //printf("%d -> %d\n", i, k);
19 }
20 }
21 }
方法二、二分图多重匹配,见模板:
View Code
 1 #include <iostream>
2 #include <cstdio>
3 #include <cstring>
4 #include <string>
5
6 using namespace std;
7
8 const int N = 110;
9
10 bool g[N][N];
11 int f[N][2];
12 int Link[N][N]; //Link[i][j]表示与i号相连的第j个 contestant;
13 bool usd[N];
14 int num[6];
15
16 int n;
17
18 bool dfs(int t) { ////在衣服顶点中寻找是否有与选手顶点x相匹配的顶点
19 int i, j;
20 for(i = 0; i < 5; i++) {
21 if(!usd[i] && g[t][i]) {
22 usd[i] = true;
23 if(num[i]) { //衣服还有
24 num[i]--;
25 Link[i][++Link[i][0]] = t; //与i衣服相连的第1个 contestant
26 return true;
27 } else {
28 for(j = 1; j <= Link[i][0]; j++) {
29 if(dfs(Link[i][j])) {
30 Link[i][j] = t; //link[i][j]表示与Y[i]匹配好的第j个contestant
31 return true;
32 }
33 }
34 }
35 }
36 }
37 return false;
38 }
39
40 int pos(char c) {
41 if(c == 'S') return 0;
42 if(c == 'M') return 1;
43 if(c == 'L') return 2;
44 if(c == 'X') return 3;
45 return 4;
46 }
47
48 int main() {
49 //freopen("data.in", "r", stdin);
50
51 string st;
52 int i, t, j;
53 while(1) {
54 cin >> st;
55 if(st == "ENDOFINPUT") break;
56 scanf("%d", &n);
57 memset(f, 0, sizeof(f));
58 memset(num, 0, sizeof(num));
59
60 for(i = 0; i < n; i++) {
61 cin >> st;
62 f[i][0] = pos(st[0]);
63 f[i][1] = pos(st[1]);
64 //printf("%d %d\n", f[i][0], f[i][1]);
65 }
66 for(i = 0; i < 5; i++) {
67 scanf("%d", &t);
68 if(!t) continue;
69 for(j = 0; j < n; j++) {
70 if(f[j][0] <= i && f[j][1] >= i) {
71 num[i]++;
72 g[j][i] = true;
73 }
74 }
75 if(num[i] > t) num[i] = t;
76 }
77 cin >> st;
78
79 int ans = 0;
80 memset(Link, 0, sizeof(Link));
81 for(i = 0; i < n; i++) {
82 memset(usd, 0, sizeof(usd));
83 if(dfs(i)) ans++;
84 }
85 if(ans == n) puts("T-shirts rock!");
86 else puts("I'd rather not wear a shirt anyway...");
87 }
88 return 0;
89 }
POJ 2536 水题,注意要死的不要活得,把模板写错了,WA了NNNNNNN次,本菜弱暴了!!T_T

POJ 2446 我叉!@¥%##@!!@#@@#¥!@。妹的把一个条件写错了,结果wa了一天多!!!!!建图,一个非k节点和他的上下左右合法节点匹配。
POJ 1325 水题。。。开始我还以为输入的i 有用呢,盯了半天。。。
POJ 2226 建图很经典,给连续出现*的行(列)进行编号,然后建图。
View Code
 1 void build() {
2 int i, j;
3 n = 0; m = 0;
4 memset(f_a, 0, sizeof(f_a));
5 memset(f_b, 0, sizeof(f_b));
6 for(i = 0; i < r; i++) {
7 for(j = 0; j < c; j++) {
8 if(map[i][j] == '*') {
9 f_a[i][j] = n;
10 if(map[i][j+1] != '*') n++;
11 }
12
13 }
14 }
15 for(i = 0; i < c; i++) {
16 for(j = 0; j < r; j++) {
17 if(map[j][i] == '*') {
18 f_b[j][i] = m;
19 if(map[j+1][i] != '*') m++;
20 }
21 }
22 }
23 memset(g, 0, sizeof(g));
24 for(i = 0; i < r; i++) {
25 for(j = 0; j < c; j++) {
26 if(map[i][j] == '*') {
27 g[f_a[i][j]][f_b[i][j]] = true;
28 //printf("%d -> %d\n", f_a[i][j], f_b[i][j]);
29 }
30 }
31 }
32 }


ps:先放放,开始刷训练计划,I'll be back~~~

posted @ 2012-02-21 20:48  AC_Von  阅读(4172)  评论(2编辑  收藏  举报