最大流最小割费用流初步
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
bzoj 3996
同类与网络流24题<2>,最大权闭合图。
D =(A * B - C)* A^T;
E = A * B;
Eij = sigma(k = (1 ~ n)) Aik * Bkj;因为 E为[1,n]的矩阵 把Eij表示为Ej.
Ej = sigma(k = (1 ~ n)) Ak * Bkj;
设F = E * A^T;
F(1, 1) = sigma(p = 1 ~n) Ep * Ap;
代入得 F = sigma(p = 1 ~ n) (sigma(k = 1 ~ n) Ak * Bkp * Ap)
G = C * A^T
G = sigma(k, 1, n) Ck * Ak;
由此可见,若要取得Bkp,则Ak和Ap必须为1,也就是Bij依赖Ai和Aj,后面的式子则是Ai的选取代价,所以得到了最大权闭合图的模型。
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 = 260005; 18 const int maxm = 751005; 19 20 struct Ed { 21 int u, v, nx, c; Ed() {} 22 Ed(int _u, int _v, int _nx, int _c) : 23 u(_u), v(_v), nx(_nx), c(_c) {} 24 } E[maxm << 1]; 25 int G[maxn], cnt; 26 void addedge(int u, int v, int c) { 27 E[cnt] = Ed(u, v, G[u], c); 28 G[u] = cnt++; 29 E[cnt] = Ed(v, u, G[v], 0); 30 G[v] = cnt++; 31 } 32 33 int s, t; 34 int level[maxn]; 35 bool bfs() { 36 static int que[maxn]; int qh(0), qt(0); 37 clr(level); 38 level[que[++qt] = s] = 1; 39 while (qh != qt) { 40 int x = que[++qh]; 41 for (int i = G[x]; i != -1; i = E[i].nx) if (E[i].c && !level[E[i].v]) 42 level[que[++qt] = E[i].v] = level[x] + 1; 43 } 44 return !!level[t]; 45 } 46 int dfs(int u, int rm) { 47 if (u == t) return rm; 48 int rm1 = rm; 49 for (int i = G[u]; i != -1; i = E[i].nx) { 50 if (E[i].c && level[E[i].v] == level[u] + 1) { 51 int flow = dfs(E[i].v, min(E[i].c, rm)); 52 E[i].c -= flow, E[i ^ 1].c += flow; 53 if ((rm -= flow) == 0) break; 54 } 55 } 56 if (rm1 == rm) level[u] = 0; 57 return rm1 - rm; 58 } 59 60 int main() { 61 int n; 62 scanf("%d", &n); 63 s = 0, t = n * n + n + 1; 64 memset(G, -1, sizeof(G)); 65 int tot(0); 66 REP(i, 0, n) rep(j, 1, n) { 67 int id; 68 scanf("%d", &id); 69 tot += id; 70 addedge(s, i * n + j, id); 71 addedge(i * n + j, i + n * n + 1, inf); 72 addedge(i * n + j, j + n * n, inf); 73 } 74 rep(i, 1, n) { 75 int id; 76 scanf("%d", &id); 77 addedge(n * n + i, t, id); 78 } 79 int ans(0); 80 while (bfs()) ans += dfs(s, 0x3f3f3f3f); 81 printf("%d\n", tot - ans); 82 return 0; 83 }
网络流24题<5> COGS 729 圆桌问题
类似于二分图匹配,给每个单位连他们人数的流量,每个单位依次给每个桌子连1的流量,每个桌子依次给超级汇点连桌子的容量的流量。
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 = 505; 18 const int maxm = 41000; 19 20 struct Ed { 21 int u, v, nx, c; Ed() {} 22 Ed(int _u, int _v, int _nx, int _c) : 23 u(_u), v(_v), nx(_nx), c(_c) {} 24 } E[maxm << 1]; 25 int G[maxn], cnt; 26 void addedge(int u, int v, int c) { 27 E[cnt] = Ed(u, v, G[u], c); 28 G[u] = cnt++; 29 E[cnt] = Ed(v, u, G[v], 0); 30 G[v] = cnt++; 31 } 32 33 int s, t; 34 int level[maxn]; 35 bool bfs() { 36 static int que[maxn]; int qh(0), qt(0); 37 clr(level); 38 level[que[++qt] = s] = 1; 39 while (qh != qt) { 40 int x = que[++qh]; 41 for (int i = G[x]; i != -1; i = E[i].nx) if (E[i].c && !level[E[i].v]) 42 level[que[++qt] = E[i].v] = level[x] + 1; 43 } 44 return !!level[t]; 45 } 46 int dfs(int u, int rm) { 47 if (u == t) return rm; 48 int rm1 = rm; 49 for (int i = G[u]; i != -1; i = E[i].nx) { 50 if (E[i].c && level[E[i].v] == level[u] + 1) { 51 int flow = dfs(E[i].v, min(rm, E[i].c)); 52 E[i].c -= flow, E[i ^ 1].c += flow; 53 if ((rm -= flow) == 0) break; 54 } 55 } 56 if (rm1 == rm) level[u] = 0; 57 return rm1 - rm; 58 } 59 60 int main() { 61 freopen("roundtable.in", "r", stdin); 62 freopen("roundtable.out", "w", stdout); 63 int n, m; 64 scanf("%d%d", &n, &m); 65 s = 0, t = n + m + 1; 66 memset(G, -1, sizeof(G)); 67 int tot(0); 68 rep(i, 1, n) { 69 int id; 70 scanf("%d", &id); 71 tot += id; 72 addedge(s, i, id); 73 } 74 rep(i, 1, n) rep(j, 1, m) addedge(i, n + j, 1); 75 rep(i, 1, m) { 76 int id; 77 scanf("%d", &id); 78 addedge(n + i, t, id); 79 } 80 int ans(0); 81 while (bfs()) ans += dfs(s, 0x3f3f3f3f); 82 if (ans < tot) puts("0"); 83 else puts("1"); 84 static int sta[maxn]; 85 int top(0); 86 rep(i, 1, n) { 87 for (int j = G[i]; j != -1; j = E[j].nx) { 88 if (E[j].c == 0) { 89 sta[++top] = E[j].v - n; 90 } 91 } 92 drep(j, top, 1) printf("%d ", sta[j]); 93 top = 0; 94 puts(""); 95 } 96 fclose(stdin); 97 fclose(stdout); 98 return 0; 99 }
2015年11月24日
网络流24题 COGS 魔术球问题
最小路径覆盖问题。
先二分答案,建图dinic即可,有一点需要注意,在连边时,i 只能向 i + 1 及其以后的边连边,否则不符合实际意义,也会使二分图满流。
1 #include <bits/stdc++.h> 2 #define rep(i, a, b) for (register 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 = 3205; 18 const int maxm = 38545; 19 20 struct Ed { 21 int u, v, nx, c; Ed() {} 22 Ed(int _u, int _v, int _nx, int _c) : 23 u(_u), v(_v), nx(_nx), c(_c) {} 24 } E[maxm << 1]; 25 int G[maxn], cnt; 26 void addedge(int u, int v, int c) { 27 E[cnt] = Ed(u, v, G[u], c); 28 G[u] = cnt++; 29 E[cnt] = Ed(v, u, G[v], 0); 30 G[v] = cnt++; 31 } 32 33 int level[maxn], s, t; 34 bool bfs() { 35 static int que[maxn]; 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(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("balla.in", "r", stdin); 61 freopen("balla.out", "w", stdout); 62 int sho; 63 scanf("%d", &sho); 64 int low = 0, high = 1605; 65 while (low < high - 1) { 66 int mid = low + high >> 1; 67 s = 0, t = (mid << 1) + 1; 68 memset(G, -1, sizeof(G)); cnt = 0; 69 rep(i, 1, mid) rep(j, i + 1, mid) { 70 int sq = sqrt(1.0 * i + j); 71 if (sq * sq == i + j) addedge(i, mid + j, 1); 72 } 73 rep(i, 1, mid) addedge(s, i, 1), addedge(i + mid, t, 1); 74 int ans(0); 75 while (bfs()) ans += dfs(s, 0x3f3f3f3f); 76 if (mid - ans <= sho) low = mid; 77 else high = mid; 78 } 79 printf("%d\n", low); 80 fclose(stdin); 81 fclose(stdout); 82 return 0; 83 }
2015年11月26日
网络流24题 10 餐巾计划
把每个点拆成两个点,一个是每天用掉的点,另一边为来源。
从S到用掉的点连接费用为0,容量为ri的边。
从来源的点向T连接费用为0,容量为ri的边。 来限制流量。
在用掉的点的集合中,i 向 i + 1 连接费用为0,容量为inf的边。
从S到来源集合中连接容量为inf,费用为P的边。
连上快洗和慢洗。
感觉第一个集合中的点中用作限制,第二个才是解决的方案。
zkw费用流:
1 #include <bits/stdc++.h> 2 #define rep(i, a, b) for (int i = a; i <= b; i++) 3 #define REP(i, a, b) for (int i = a; i < b; i++) 4 #define drep(i, a, b) for (int i = a; i >= b; i--) 5 #define clr(x) memset(x, 0, sizeof(x)) 6 #define pb push_back 7 #define mp make_pair 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 = 405, maxm = 40605; 18 struct Ed { 19 int u, v, nx, c, s; Ed() {}; 20 Ed (int _u, int _v, int _nx, int _c, int _s) : 21 u(_u), v(_v), nx(_nx), c(_c), s(_s) {} 22 } E[maxm << 1]; 23 int G[maxn], cnt; 24 void addedge(int u, int v, int c, int s) { 25 E[cnt] = Ed(u, v, G[u], c, s); 26 G[u] = cnt++; 27 E[cnt] = Ed(v, u, G[v], 0, -s); 28 G[v] = cnt++; 29 } 30 31 int s, t; 32 int dis[maxn], vis[maxn]; 33 bool spfa() { 34 static int que[maxm]; int qh(0), qt(0); 35 memset(dis, 0x3f, sizeof(dis)); 36 clr(vis); 37 vis[que[++qt] = s] = 1; dis[s] = 0; 38 while (qh != qt) { 39 int x = que[++qh]; vis[x] = 0; 40 for (int i = G[x]; i != -1; i = E[i].nx) { 41 if (E[i].c && E[i].s + dis[x] < dis[E[i].v]) { 42 dis[E[i].v] = dis[x] + E[i].s; 43 if (!vis[E[i].v]) que[++qt] = E[i].v, vis[E[i].v] = 1; 44 } 45 } 46 } 47 return dis[t] != 0x3f3f3f3f; 48 } 49 50 int ans; 51 int dfs(int u, int rm) { 52 vis[u] = 1; 53 if (u == t) return rm; 54 int rm1 = rm; 55 for (int i = G[u]; i != -1; i = E[i].nx) { 56 if (dis[u] + E[i].s == dis[E[i].v] && E[i].c && !vis[E[i].v]) { 57 int flow = dfs(E[i].v, min(rm, E[i].c)); 58 E[i].c -= flow, E[i ^ 1].c += flow; 59 ans += flow * E[i].s; 60 if ((rm -= flow) == 0) break; 61 } 62 } 63 if (rm1 == rm) dis[u] = 0; 64 return rm1 - rm; 65 } 66 67 int a[maxn]; 68 int main() { 69 freopen("napkin.in", "r", stdin); 70 freopen("napkin.out", "w", stdout); 71 int n; 72 scanf("%d", &n); 73 rep(i, 1, n) scanf("%d", &a[i]); 74 int P, M, F, N, S; 75 scanf("%d%d%d%d%d", &P, &M, &F, &N, &S); 76 memset(G, -1, sizeof(G)); s = 0, t = (n << 1) + 1; 77 rep(i, 1, n) addedge(s, i, a[i], 0), addedge(s, n + i, inf, P), addedge(i + n, t, a[i], 0); 78 REP(i, 1, n) addedge(i, i + 1, inf, 0); 79 rep(i, 1, n) { 80 if (i + M <= n) addedge(i, i + M + n, inf, F); 81 if (i + N <= n) addedge(i, i + N + n, inf, S); 82 } 83 84 while (spfa()) clr(vis), dfs(s, 0x3f3f3f3f); 85 printf("%d\n", ans); 86 fclose(stdin); 87 fclose(stdout); 88 return 0; 89 }
普通费用流:
1 #include <bits/stdc++.h> 2 #define rep(i, a, b) for (int i = a; i <= b; i++) 3 #define REP(i, a, b) for (int i = a; i < b; i++) 4 #define drep(i, a, b) for (int i = a; i >= b; i--) 5 #define pb push_back 6 #define mp make_pair 7 #define xx first 8 #define yy second 9 using namespace std; 10 typedef long long i64; 11 typedef pair<int, int> pii; 12 const int inf = ~0U >> 1; 13 const i64 INF = ~0ULL >> 1; 14 //***************************** 15 16 const int maxn = 405, maxm = 40605; 17 struct Ed { 18 int u, v, nx, c, s; Ed() {}; 19 Ed (int _u, int _v, int _nx, int _c, int _s) : 20 u(_u), v(_v), nx(_nx), c(_c), s(_s) {} 21 } E[maxm << 1]; 22 int G[maxn], cnt; 23 void addedge(int u, int v, int c, int s) { 24 E[cnt] = Ed(u, v, G[u], c, s); 25 G[u] = cnt++; 26 E[cnt] = Ed(v, u, G[v], 0, -s); 27 G[v] = cnt++; 28 } 29 30 bool vis[maxn]; 31 int s, t; 32 int pre[maxn]; 33 bool spfa() { 34 static int que[maxm]; int qh(0), qt(0); 35 static int dis[maxn]; 36 memset(dis, 0x3f, sizeof(dis)); 37 memset(vis, 0, sizeof(vis)); 38 vis[que[++qt] = s] = 1; 39 dis[s] = 0; 40 while (qh != qt) { 41 int x = que[++qh]; 42 vis[x] = 0; 43 for (int i = G[x]; i != -1; i = E[i].nx) { 44 if (E[i].c && dis[x] + E[i].s < dis[E[i].v]) { 45 dis[E[i].v] = dis[x] + E[i].s; 46 pre[E[i].v] = i; 47 if (!vis[E[i].v]) { 48 vis[E[i].v] = 1; 49 que[++qt] = E[i].v; 50 } 51 } 52 } 53 } 54 if (dis[t] == 0x3f3f3f3f) return false; 55 return true; 56 } 57 58 int a[maxn]; 59 int main() { 60 freopen("napkin.in", "r", stdin); 61 freopen("napkin.out", "w", stdout); 62 int n; 63 scanf("%d", &n); 64 rep(i, 1, n) scanf("%d", &a[i]); 65 int P, M, F, N, S; 66 scanf("%d%d%d%d%d", &P, &M, &F, &N, &S); 67 68 memset(G, -1, sizeof(G)); 69 s = 0, t = (n << 1) + 1; 70 rep(i, 1, n) { addedge(s, i, a[i], 0); addedge(i + n, t, a[i], 0); } 71 REP(i, 1, n) addedge(i, i + 1, inf, 0); 72 rep(i, 1, n) addedge(s, i + n, inf, P); 73 rep(i, 1, n) { 74 if (i + M <= n) addedge(i, i + M + n, inf, F); 75 if (i + N <= n) addedge(i, i + N + n, inf, S); 76 } 77 int ans(0); 78 pre[s] = -1; 79 while (spfa()) { 80 int flow = inf; 81 for (int i = pre[t]; i != -1; i = pre[E[i].u]) { 82 flow = min(flow, E[i].c); 83 } 84 for (int i = pre[t]; i != -1; i = pre[E[i].u]) { 85 E[i].c -= flow, E[i ^ 1].c += flow; 86 ans += flow * E[i].s; 87 } 88 } 89 printf("%d\n", ans); 90 }
网络流24题 11 航空路线问题
可以dp多线程。
同样,拆点,一个点为入点,一个为出点。
S到1的入点连接 【容量为2,费用为1】的边,n的出点连接 【容量为2,费用为0】的边,每条航线连接【容量为1,费用为1】的边,每个点出点到自己的入点连接【容量为1,费用为0】的边。(和第一个点和最后一个点相连的边容量均为2)。
如果最大流不够,-1。
因为要求最大费用最大流,所以把边权建成-1就好。
1 #include <bits/stdc++.h> 2 #define rep(i, a, b) for (int i = a; i <= b; i++) 3 #define REP(i, a, b) for (int i = a; i < b; i++) 4 #define drep(i, a, b) for (int i = a; i >= b; i--) 5 #define clr(x) memset(x, 0, sizeof(x)) 6 #define pb push_back 7 #define mp make_pair 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 = 205, maxm = 10005; 18 struct Ed { 19 int u, v, nx, c, s; Ed() {} 20 Ed(int _u, int _v, int _nx, int _c, int _s) : 21 u(_u), v(_v), nx(_nx), c(_c), s(_s) {} 22 } E[maxm << 1]; 23 int G[maxn], cnt; 24 void addedge(int u, int v, int c, int s) { 25 E[cnt] = Ed(u, v, G[u], c, s); 26 G[u] = cnt++; 27 E[cnt] = Ed(v, u, G[v], 0, -s); 28 G[v] = cnt++; 29 } 30 31 int s, t, pre[maxn]; 32 int vis[maxn], dis[maxn]; 33 bool spfa() { 34 static int que[maxm]; int qh(0), qt(0); 35 clr(vis), memset(dis, 0x3f, sizeof(dis)); 36 vis[que[++qt] = s] = 1, dis[s] = 0; 37 while (qh != qt) { 38 int x = que[++qh]; vis[x] = 0; 39 for (int i = G[x]; i != -1; i = E[i].nx) { 40 if (E[i].c && dis[x] + E[i].s < dis[E[i].v]) { 41 pre[E[i].v] = i; 42 dis[E[i].v] = dis[x] + E[i].s; 43 if (!vis[E[i].v]) vis[que[++qt] = E[i].v] = 1; 44 } 45 } 46 } 47 return dis[t] != 0x3f3f3f3f; 48 } 49 50 map <string, int> M; 51 string ch[maxn]; 52 int main() { 53 int n, m; 54 string str; 55 cin >> n >> m; 56 rep(i, 1, n) { 57 cin >> str; 58 ch[i] = str; 59 M[str] = i; 60 } 61 s = 0, t = (n << 1) + 1; 62 memset(G, -1, sizeof(G)); 63 addedge(s, 1, 2, -1), addedge(n << 1, t, 2, 0); 64 while (m--) { 65 int x, y; 66 cin >> str; x = M[str]; 67 cin >> str; y = M[str]; 68 if (x == 1 || y == n) addedge(x, y + n, 2, -1); 69 else addedge(x, y + n, 1, -1); 70 } 71 REP(i, 2, n) addedge(i + n, i, 1, 0); 72 addedge(1 + n, 1, 2, 0), addedge(n + n, n, 2, 0); 73 pre[0] = -1; 74 int ans(0), f(0); 75 while (spfa()) { 76 int flow = inf; 77 for (int i = pre[t]; i != -1; i = pre[E[i].u]) 78 flow = min(flow, E[i].c); 79 f += flow; 80 for (int i = pre[t]; i != -1; i = pre[E[i].u]) { 81 E[i].c -= flow, E[i ^ 1].c += flow; 82 ans += E[i].s * flow; 83 } 84 } 85 if (f < 2) puts("-1"); 86 else { 87 static int pri[maxn]; int top(0); 88 cout << -ans - 2 << endl; 89 int k = 1; 90 while (1) { 91 pri[++top] = k; 92 for (int i = G[k]; i != -1; i = E[i].nx) { 93 if (E[i].v - n <= k) continue; 94 if (E[i ^ 1].c != 0) { 95 E[i].c += 1, E[i ^ 1].c -= 1; 96 k = E[i].v - n; 97 break; 98 } 99 } 100 if (k == n) break; 101 } 102 k = n + n; 103 while (1) { 104 pri[++top] = k - n; 105 for (int i = G[k]; i != -1; i = E[i].nx) { 106 if (E[i].v >= k - n) continue; 107 if (E[i].c != 0) { 108 k = E[i].v + n; 109 break; 110 } 111 } 112 if (k == n + 1) break; 113 } 114 pri[++top] = k - n; 115 for (int i = top; i >= 1; i--) cout << ch[pri[i]] << endl; 116 } 117 return 0; 118 }