[luoguP2754] 星际转移问题(最大流)
不同的时间每个飞船所在的地点不同,给我们启示按照时间构建分层图。
同一个地点 x <x, dayi - 1> -> <x, dayi> 连一条容量为 INF 的边,因为人们可以在一个地点等待
艘飞船的路径 如果 a 的下一站是 b,那么 <a, dayi - 1> -> <b, dayi> 连一条容量为该飞船容量的边,表示可以 a 坐飞船到 b
增加超级源点 s,s 和地球连一条容量为 k 的边
增加超级汇点 t,月球的每一天都和 t 连一条容量为 INF 的边
枚举天数,跑最大流,直到 max_flow == k,输出天数
对于判断是否能到达,用并查集判断连通性
——代码
1 #include <queue> 2 #include <cstdio> 3 #include <cstring> 4 #include <iostream> 5 #define N 1000001 6 #define INF 1e9 7 #define min(x, y) ((x) < (y) ? (x) : (y)) 8 9 int n, m, k, s, t, cnt, sum; 10 int f[N], c[N], p[N], b[101][101], dis[N]; 11 int head[N], to[N << 1], next[N << 1], val[N << 1]; 12 13 inline int C(int t, int x) 14 { 15 return t * (n + 2) + x; 16 } 17 18 inline int read() 19 { 20 int x = 0, f = 1; 21 char ch = getchar(); 22 for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1; 23 for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0'; 24 return x * f; 25 } 26 27 inline int find(int x) 28 { 29 return x == f[x] ? x : f[x] = find(f[x]); 30 } 31 32 inline void add(int x, int y, int z) 33 { 34 to[cnt] = y; 35 val[cnt] = z; 36 next[cnt] = head[x]; 37 head[x] = cnt++; 38 } 39 40 inline bool bfs() 41 { 42 int i, u, v; 43 std::queue <int> q; 44 memset(dis, -1, sizeof(dis)); 45 q.push(s); 46 dis[s] = 0; 47 while(!q.empty()) 48 { 49 u = q.front(), q.pop(); 50 for(i = head[u]; i ^ -1; i = next[i]) 51 { 52 v = to[i]; 53 if(val[i] && dis[v] == -1) 54 { 55 dis[v] = dis[u] + 1; 56 if(v == t) return 1; 57 q.push(v); 58 } 59 } 60 } 61 return 0; 62 } 63 64 inline int dfs(int u, int maxflow) 65 { 66 if(u == t) return maxflow; 67 int v, d, ret = 0; 68 for(int i = head[u]; i ^ -1; i = next[i]) 69 { 70 v = to[i]; 71 if(val[i] && dis[v] == dis[u] + 1) 72 { 73 d = dfs(v, min(val[i], maxflow - ret)); 74 ret += d; 75 val[i] -= d; 76 val[i ^ 1] += d; 77 if(ret == maxflow) return ret; 78 } 79 } 80 if(ret ^ maxflow) dis[u] = -1; 81 return ret; 82 } 83 84 int main() 85 { 86 int i, j, x, y, d; 87 n = read(); 88 m = read(); 89 k = read(); 90 s = N - 1, t = N - 2; 91 for(i = 1; i <= n + 2; i++) f[i] = i; 92 for(i = 1; i <= m; i++) 93 { 94 c[i] = read(); 95 p[i] = read(); 96 for(j = 0; j < p[i]; j++) 97 { 98 b[i][j] = read() + 2; 99 if(j) 100 { 101 x = find(b[i][j - 1]); 102 y = find(b[i][j]); 103 if(x ^ y) f[x] = y; 104 } 105 } 106 } 107 if(find(1) ^ find(2)) 108 { 109 printf("0\n"); 110 return 0; 111 } 112 d = 0; 113 memset(head, -1, sizeof(head)); 114 add(s, 2, k); 115 add(2, s, 0); 116 while(1) 117 { 118 d++; 119 for(i = 1; i <= n + 2; i++) 120 { 121 add(C(d - 1, i), C(d, i), INF); 122 add(C(d, i), C(d - 1, i), 0); 123 } 124 for(i = 1; i <= m; i++) 125 { 126 add(C(d - 1, b[i][(d - 1) % p[i]]), C(d, b[i][d % p[i]]), c[i]); 127 add(C(d, b[i][d % p[i]]), C(d - 1, b[i][(d - 1) % p[i]]), 0); 128 } 129 add(C(d, 1), t, INF); 130 add(t, C(d, 1), 0); 131 while(bfs()) sum += dfs(s, INF); 132 if(sum == k) 133 { 134 printf("%d\n", d); 135 return 0; 136 } 137 } 138 }