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~~~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM