[SWUSTOJ1737] 太空飞行计划问题(最大权闭合子图,记录路径)
Posted tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[SWUSTOJ1737] 太空飞行计划问题(最大权闭合子图,记录路径)相关的知识,希望对你有一定的参考价值。
题目链接:https://www.oj.swust.edu.cn/problem/show/1737
很经典的建图,但是需要记录路径。
vis数组标记点是否被扩展,在每次dinic通过bfs扩展的时候假如被扩展的点,最后一次bfs随后不再有增广路便是最终结果。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef struct Edge { 5 int u, v, w, ww, next; 6 }Edge; 7 8 const int inf = 0x7f7f7f7f; 9 const int maxn = 3010; 10 const int maxm = maxn << 2; 11 int cnt, dhead[maxn]; 12 int cur[maxn], dd[maxn]; 13 bool vis[maxn]; 14 Edge dedge[maxm]; 15 int S, T, N; 16 17 void init() { 18 memset(dhead, -1, sizeof(dhead)); 19 for(int i = 0; i < maxn; i++) dedge[i].next = -1; 20 S = 0; cnt = 0; 21 } 22 23 void adde(int u, int v, int w, int c1=0) { 24 dedge[cnt].u = u; dedge[cnt].v = v; dedge[cnt].w = w; dedge[cnt].ww = w; 25 dedge[cnt].next = dhead[u]; dhead[u] = cnt++; 26 dedge[cnt].u = v; dedge[cnt].v = u; dedge[cnt].w = c1; dedge[cnt].ww = c1; 27 dedge[cnt].next = dhead[v]; dhead[v] = cnt++; 28 } 29 30 bool bfs(int s, int t, int n) { 31 memset(vis, 0, sizeof(vis)); 32 queue<int> q; 33 for(int i = 0; i < n; i++) dd[i] = inf; 34 dd[s] = 0; 35 q.push(s); 36 while(!q.empty()) { 37 int u = q.front(); q.pop(); 38 for(int i = dhead[u]; ~i; i = dedge[i].next) { 39 if(dd[dedge[i].v] > dd[u] + 1 && dedge[i].w > 0) { 40 dd[dedge[i].v] = dd[u] + 1; 41 vis[dedge[i].v] = 1; 42 if(dedge[i].v == t) return 1; 43 q.push(dedge[i].v); 44 } 45 } 46 } 47 return 0; 48 } 49 50 int dinic(int s, int t, int n) { 51 int st[maxn], top; 52 int u; 53 int flow = 0; 54 while(bfs(s, t, n)) { 55 for(int i = 0; i < n; i++) cur[i] = dhead[i]; 56 u = s; top = 0; 57 while(cur[s] != -1) { 58 if(u == t) { 59 int tp = inf; 60 for(int i = top - 1; i >= 0; i--) { 61 tp = min(tp, dedge[st[i]].w); 62 } 63 flow += tp; 64 for(int i = top - 1; i >= 0; i--) { 65 dedge[st[i]].w -= tp; 66 dedge[st[i] ^ 1].w += tp; 67 if(dedge[st[i]].w == 0) top = i; 68 } 69 u = dedge[st[top]].u; 70 } 71 else if(cur[u] != -1 && dedge[cur[u]].w > 0 && dd[u] + 1 == dd[dedge[cur[u]].v]) { 72 st[top++] = cur[u]; 73 u = dedge[cur[u]].v; 74 } 75 else { 76 while(u != s && cur[u] == -1) { 77 u = dedge[st[--top]].u; 78 } 79 cur[u] = dedge[cur[u]].next; 80 } 81 } 82 } 83 return flow; 84 } 85 86 int n, m; 87 char tmp[maxm]; 88 vector<int> s; 89 90 int main() { 91 // freopen("in", "r", stdin); 92 int pay; 93 while(~scanf("%d%d",&n,&m)) { 94 init(); 95 S = 0, T = m + n + 1, N = T + 1; 96 int pos = 0; 97 for(int i = 1; i <= n; i++) { 98 scanf("%d",&pay); 99 pos += pay; 100 adde(S, i, pay); 101 char p = getchar(); 102 while((p = getchar()) != ‘\n‘) { 103 pay = p - ‘0‘; 104 while((p = getchar()) && p >= ‘0‘ && p <= ‘9‘) pay = pay * 10 + p - ‘0‘; 105 adde(i, pay+n, inf); 106 if(p == ‘\n‘) break; 107 } 108 } 109 for(int i = 1; i <= m; i++) { 110 scanf("%d", &pay); 111 adde(n+i, T, pay); 112 } 113 int ret = pos - dinic(S, T, N); 114 s.clear(); 115 for(int i = 1; i <= n; i++) { 116 if(vis[i]) s.push_back(i); 117 } 118 printf("%d", s[0]); 119 for(int i = 1; i < s.size(); i++) printf(" %d", s[i]); 120 printf("\n"); 121 s.clear(); 122 for(int i = n+1; i <= n+m; i++) { 123 if(vis[i]) s.push_back(i-n); 124 } 125 printf("%d", s[0]); 126 for(int i = 1; i < s.size(); i++) printf(" %d", s[i]); 127 printf("\n"); 128 printf("%d\n", ret); 129 } 130 return 0; 131 }
以上是关于[SWUSTOJ1737] 太空飞行计划问题(最大权闭合子图,记录路径)的主要内容,如果未能解决你的问题,请参考以下文章
PowerOJ1737&网络流24题太空飞行计划问题(最小割)
LuoguP2762 太空飞行计划问题(最大权闭合子图,最小割)