标签:
2015年11月23日
网络流24题<1> COGS 14
二分图匹配。
Dinic:
1 #include <bits/stdc++.h> 2 #define rep(i, a, b) for (int i = a; i <= b; i++) 3 #define drep(i, a, b) for (int i = a; i >= b; i--) 4 #define REP(i, a, b) for (int i = a; i < b; i++) 5 #define pb push_back 6 #define mp make_pair 7 #define clr(x) memset(x, 0, sizeof(x)) 8 #define xx first 9 #define yy second 10 using namespace std; 11 typedef long long i64; 12 typedef pair<int, int> pii; 13 const int inf = ~0U>>1; 14 const i64 INF = ~0ULL>>1; 15 //*************************** 16 17 const int maxn = 105; 18 struct Ed { 19 int u, v, nx, c; Ed() {} 20 Ed(int _u, int _v, int _nx, int _c) : 21 u(_u), v(_v), nx(_nx), c(_c) {} 22 } E[3005]; 23 int G[105], cnt; 24 void addedge(int x, int y, int v) { 25 E[cnt] = Ed(x, y, G[x], v); 26 G[x] = cnt++; 27 E[cnt] = Ed(y, x, G[y], 0); 28 G[y] = cnt++; 29 } 30 31 int s, t; 32 33 int level[maxn]; 34 bool bfs() { 35 static int que[maxn]; int qt(0), qh(0); 36 clr(level); 37 level[que[++qt] = s] = 1; 38 while (qt != qh) { 39 int x = que[++qh]; 40 for (int i = G[x]; i != -1; i = E[i].nx) if (E[i].c && !level[E[i].v]) 41 level[que[++qt] = E[i].v] = level[x] + 1; 42 } 43 return !!level[t]; 44 } 45 int dfs(int u, int rm) { 46 if (u == t) return rm; 47 int rm1 = rm; 48 for (int i = G[u]; i != -1; i = E[i].nx) { 49 if (E[i].c && level[E[i].v] == level[u] + 1) { 50 int flow = dfs(E[i].v, min(E[i].c, rm)); 51 E[i].c -= flow, E[i ^ 1].c += flow; 52 if ((rm -= flow) == 0) break; 53 } 54 } 55 if (rm1 == rm) level[u] = 0; 56 return rm1 - rm; 57 } 58 59 int main() { 60 freopen("flyer.in", "r", stdin); 61 freopen("flyer.out", "w", stdout); 62 int n, n1; 63 while (~scanf("%d%d", &n, &n1)) { 64 s = 0, t = n + 1; 65 memset(G, -1, sizeof(G)); 66 int x, y; 67 while (~scanf("%d%d", &x, &y)) addedge(x, y, 1); 68 rep(i, 1, n1) addedge(s, i, 1); 69 rep(i, n1 + 1, n) addedge(i, t, 1); 70 int ans(0); 71 while (bfs()) ans += dfs(s, 0x3f3f3f3f); 72 printf("%d\n", ans); 73 } 74 fclose(stdin); 75 fclose(stdout); 76 return 0; 77 }
匈牙利:
1 #include <bits/stdc++.h> 2 #define rep(i, a, b) for (int i = a; i <= b; i++) 3 #define drep(i, a, b) for (int i = a; i >= b; i--) 4 #define REP(i, a, b) for (int i = a; i < b; i++) 5 #define pb push_back 6 #define mp make_pair 7 #define clr(x) memset(x, 0, sizeof(x)) 8 #define xx first 9 #define yy second 10 using namespace std; 11 typedef long long i64; 12 typedef pair<int, int> pii; 13 const int inf = ~0U>>1; 14 const i64 INF = ~0ULL>>1; 15 //*************************** 16 17 const int maxn = 105; 18 struct Ed { 19 int u, v, nx, c; Ed() {} 20 Ed(int _u, int _v, int _nx) : 21 u(_u), v(_v), nx(_nx) {} 22 } E[3005]; 23 int G[105], cnt; 24 void addedge(int x, int y) { 25 E[cnt] = Ed(x, y, G[x]); 26 G[x] = cnt++; 27 } 28 29 bool used[maxn]; 30 int girl[maxn]; 31 bool find(int x) { 32 for (int i = G[x]; i != -1; i = E[i].nx) { 33 if (used[E[i].v]) continue; 34 used[E[i].v] = 1; 35 if (!girl[E[i].v] || find(girl[E[i].v])) { 36 girl[E[i].v] = x; 37 return true; 38 } 39 } 40 return false; 41 } 42 int main() { 43 freopen("flyer.in", "r", stdin); 44 freopen("flyer.out", "w", stdout); 45 int n, n1; 46 while (~scanf("%d%d", &n, &n1)) { 47 int x, y; 48 memset(G, -1, sizeof(G)); 49 while (~scanf("%d%d", &x, &y)) { 50 addedge(x, y); 51 } 52 clr(girl); 53 int ans(0); 54 rep(i, 1, n1) { 55 clr(used); 56 if (find(i)) ans++; 57 } 58 printf("%d\n", ans); 59 } 60 61 }
网络流24题<2> COGS 727
该问题的一般模型为最大权闭合图。
[建模方法]
把每个实验看作二分图X集合中的顶点,每个设备看作二分图Y集合中的顶点,增加源S和汇T。
1、从S向每个Xi连接一条容量为该点收入的有向边。
2、从Yi向T连接一条容量为该点支出的有向边。
3、如果一个实验i需要设备j,连接一条从Xi到Yj容量为无穷大的有向边。
用割来确定答案。
设S-T割中的S割为选定的答案,A为实验集合,B为器材编号。
ans:被选中的A集合中的顶点的权值 - 被选中的B集合中的顶点的权值
Cut:没有被选中的A集合中的顶点的权值 + 被选中的B集合中的顶点的权值 + 被选中的A集合中与没有被选中的B集合中的边的Sum (一些inf的和)
Total:所有A集合中的顶点的权值
Total - Cut = ans
最小割时没有Cut里的第三项,所以最小化Cut,最大流。
1 #include <bits/stdc++.h> 2 #define rep(i, a, b) for (int i = a; i <= b; i++) 3 #define drep(i, a, b) for (int i = a; i >= b; i--) 4 #define REP(i, a, b) for (int i = a; i < b; i++) 5 #define pb push_back 6 #define mp make_pair 7 #define clr(x) memset(x, 0, sizeof(x)) 8 #define xx first 9 #define yy second 10 using namespace std; 11 typedef long long i64; 12 typedef pair<int, int> pii; 13 const int inf = 0x3f3f3f3f; 14 const i64 INF = ~0ULL>>1; 15 //*************************** 16 17 const int maxn = 205; 18 struct Ed { 19 int u, v, nx, c; Ed() {} 20 Ed(int _u, int _v, int _nx, int _c) : 21 u(_u), v(_v), nx(_nx), c(_c) {} 22 } E[10205]; 23 int G[maxn], cnt; 24 void addedge(int x, int y, int v) { 25 E[cnt] = Ed(x, y, G[x], v); 26 G[x] = cnt++; 27 E[cnt] = Ed(y, x, G[y], 0); 28 G[y] = cnt++; 29 } 30 31 int s, t; 32 int level[maxn]; 33 bool bfs() { 34 static int que[maxn]; int qh(0), qt(0); 35 clr(level); 36 level[que[++qt] = s] = 1; 37 while (qh != qt) { 38 int x = que[++qh]; 39 for (int i = G[x]; i != -1; i = E[i].nx) if (E[i].c && !level[E[i].v]) 40 level[que[++qt] = E[i].v] = level[x] + 1; 41 } 42 return !!level[t]; 43 } 44 int dfs(int u, int rm) { 45 if (u == t) return rm; 46 int rm1 = rm; 47 for (int i = G[u]; i != -1; i = E[i].nx) { 48 if (E[i].c && level[E[i].v] == level[u] + 1) { 49 int flow = dfs(E[i].v, min(rm, E[i].c)); 50 E[i].c -= flow, E[i ^ 1].c += flow; 51 if ((rm -= flow) == 0) break; 52 } 53 } 54 if (rm1 == rm) level[u] = 0; 55 return rm1 - rm; 56 } 57 58 char ch[100005]; 59 int main() { 60 freopen("shuttle.in", "r", stdin); 61 freopen("shuttle.out", "w", stdout); 62 int n, m; 63 int tot(0); 64 scanf("%d%d", &n, &m); 65 memset(G, -1, sizeof(G)); 66 s = 0, t = n + m + 1; 67 rep(i, 1, n) { 68 int val; 69 scanf("%d ", &val); 70 tot += val; 71 addedge(s, i, val); 72 fgets(ch, 100000, stdin); 73 int id(0); 74 for (int j = 0; ch[j]; j++) { 75 if (ch[j] == ‘ ‘ || ch[j] == ‘\n‘ || ch[j] == ‘\r‘) { 76 if (id) addedge(i, id + n, inf); 77 id = 0; 78 } 79 else { 80 id = id * 10 + ch[j] - ‘0‘; 81 } 82 } 83 } 84 rep(i, 1, m) { 85 int val; 86 scanf("%d", &val); 87 addedge(n + i, t, val); 88 } 89 int ans(0); 90 while (bfs()) ans += dfs(s, 0x3f3f3f3f); 91 rep(i, 1, n) if (level[i]) printf("%d ", i); 92 puts(""); 93 rep(i, 1, m) if (level[i + n]) printf("%d ", i); 94 puts(""); 95 printf("%d\n", tot - ans); 96 return 0; 97 }
网络流24题<3> COGS 728
二分图最大匹配。假设一开始n个点自己是一条链,那么此时有n条链,假设可以匹配一个,那么路径数就会减一,所以跑出最大匹配即可。
懒,只写了dinic:
1 #include <bits/stdc++.h> 2 #define rep(i, a, b) for (int i = a; i <= b; i++) 3 #define drep(i, a, b) for (int i = a; i >= b; i--) 4 #define REP(i, a, b) for (int i = a; i < b; i++) 5 #define pb push_back 6 #define mp make_pair 7 #define clr(x) memset(x, 0, sizeof(x)) 8 #define xx first 9 #define yy second 10 using namespace std; 11 typedef long long i64; 12 typedef pair<int, int> pii; 13 const int inf = 0x3f3f3f3f; 14 const i64 INF = ~0ULL>>1; 15 //*************************** 16 17 const int maxn = 305; 18 19 struct Ed { 20 int u, v, c, nx; Ed() {} 21 Ed(int _u, int _v, int _c, int _nx) : 22 u(_u), v(_v), c(_c), nx(_nx) {} 23 } E[13005]; 24 int G[305], cnt; 25 void addedge(int u, int v, int c) { 26 E[cnt] = Ed(u, v, c, G[u]); 27 G[u] = cnt++; 28 E[cnt] = Ed(v, u, 0, G[v]); 29 G[v] = cnt++; 30 } 31 32 int level[maxn]; 33 int s, t; 34 bool bfs() { 35 static int que[305]; int qh(0), qt(0); 36 clr(level); 37 level[que[++qt] = s] = 1; 38 while (qh != qt) { 39 int x = que[++qh]; 40 for (int i = G[x]; i != -1; i = E[i].nx) if (E[i].c && !level[E[i].v]) 41 level[que[++qt] = E[i].v] = level[x] + 1; 42 } 43 return !!level[t]; 44 } 45 int dfs(int u, int rm) { 46 if (u == t) return rm; 47 int rm1 = rm; 48 for (int i = G[u]; i != -1; i = E[i].nx) { 49 if (E[i].c && level[E[i].v] == level[u] + 1) { 50 int flow = dfs(E[i].v, min(rm, E[i].c)); 51 E[i].c -= flow, E[i ^ 1].c += flow; 52 if ((rm -= flow) == 0) break; 53 } 54 } 55 if (rm1 == rm) level[u] = 0; 56 return rm1 - rm; 57 } 58 59 int main() { 60 freopen("path3.in", "r", stdin); 61 freopen("path3.out", "w", stdout); 62 int n, m; 63 scanf("%d%d", &n, &m); 64 s = 0, t = (n << 1) + 1; 65 memset(G, -1, sizeof(G)); 66 rep(i, 1, m) { 67 int x, y; 68 scanf("%d%d", &x, &y); 69 addedge(x, y + n, 1); 70 } 71 rep(i, 1, n) { 72 addedge(s, i, 1); 73 addedge(i + n, t, 1); 74 } 75 while (bfs()) dfs(s, 0x3f3f3f3f); 76 static int nxt[maxn], frm[maxn]; 77 rep(i, 1, n) { 78 for (int j = G[i]; j != -1; j = E[j].nx) { 79 if (E[j].v <= n) continue; 80 if (E[j].c == 0) { 81 nxt[i] = E[j].v - n, frm[E[j].v - n] = i; 82 break; 83 } 84 } 85 } 86 int ans(0); 87 rep(i, 1, n) { 88 if (frm[i] == 0) { 89 int k = i; 90 while (k) { 91 printf("%d ", k); 92 k = nxt[k]; 93 } 94 puts(""); 95 ans++; 96 } 97 } 98 printf("%d\n", ans); 99 fclose(stdin); 100 fclose(stdout); 101 return 0; 102 }
匈牙利算法请见友链中的Ngshily. http://www.cnblogs.com/Ngshily/p/4988909.html
标签:
原文地址:http://www.cnblogs.com/y7070/p/4988800.html