【网络流】太空飞行计划问题
2012-02-05 10:32
337 查看
![](http://hi.csdn.net/attachment/201202/5/0_1328407927TCt9.gif)
这道题和前两天的最大获利是一模一样的,只是要输出方案,可以参见前两天的解题报告。
也可以看看兽哥http://user.qzone.qq.com/446801569?ptlang=2052,写得比较好
反正就是 获利=期望总收益-最小割。
输出方案的时候,纠结了很久。还是错了。正确的方法有两个。OJ说要从T向上遍历,最后输出的点都是必须遍历的。
证明:因为该点要选,必定是要盈利的点(假设不盈利,则会使总利润减少而不增加,不如不选),所以收益大于成本,所以割切在仪器那一边,所以要选的实验和仪器都在实验集合T集中,在sap过程中最后结束的标志是出现了断层(即割切),所以从T向上遍历,染过色的点,必然都属于T集。
实现方案一种即为遍历染色,另外一种是找到断层(vd[i]为零的),把所有在断层和T之间的点输出来。
#include <cstdio> long t; long s; long n; long m; struct node { long i; long f; node* b; node* next; }; node* head[200]; long vd[200]; long d[200]; long size = 0; long p[200]; long c[200]; bool used[200]; const long inf = 0x7fff0000; inline long min(long a,long b) { if (a < b) return a; return b; } long sap(long u,long flow) { if (u == t) { return flow; } long count = 0; for (node* vv=head[u];vv;vv=vv->next) { long v = vv->i; if (d[u]-d[v]==1) { long f = vv->f; long tmp=sap(v,min(flow-count,f)); vv->f -= tmp; vv->b->f += tmp; count += tmp; if (count == flow) { return count; } } } if (d[s] >= size) { return count; } vd[d[u]]--; if (vd[d[u]] == 0) { d[s] = size; } d[u]++; vd[d[u]]++; return count; } void insert(long a,long b,long c,long d) { node* nn = new node; nn->i = b; nn->f = c; nn->next = head[a]; head[a] = nn; nn = new node; nn->i = a; nn->f = d; nn->next = head[b]; head[b] = nn; head[a]->b = head[b]; head[b]->b = head[a]; } void dfs(long u) { used[u] = true; if (u == s) return; for (node* vv=head[u];vv;vv=vv->next) { // if (d[v]-d[u]==1&&!used[vv->i]) if (vv->b->f>0&&!used[vv->i]) { dfs(vv->i); } } } int main() { freopen("shut.in","r",stdin); freopen("shut.out","w",stdout); scanf("%ld%ld",&n,&m); size = n+m+2; s = size; t = size-1; long amount = 0; for (long i=1;i<n+1;i++) { scanf("%ld",p+i); long b;char c; while (1) { scanf("%ld%c",&b,&c); insert(b+n,i,inf,0); if (c == '\n') break; } insert(i,t,p[i],0); amount += p[i]; } for (long i=n+1;i<n+m+1;i++) { scanf("%ld",c+i); insert(s,i,c[i],0); } long ans = 0; vd[0] = size; while (d[s] < size) { ans += sap(s,inf); } dfs(t); for (long i=1;i<n+1;i++) { if (used[i]) printf("%ld ",i); } printf("\n"); for (long i=n+1;i<n+m+1;i++) { if (used[i]) printf("%ld ",i-n); } printf("\n%ld\n",amount-ans); return 0; }
相关文章推荐
- 网络流24题2 太空飞行计划问题
- 网络流2太空飞行计划问题
- [网络流专练2][太空城市飞行计划问题]
- 【网络流24题】太空飞行计划问题 …
- 线性规划与网络流24题 02太空飞行计划问题 最小割
- 【网络流二十四题 太空飞行计划问题】【最大权闭合图->最小割】
- 线性规划与网络流24题 太空飞行计划问题 (最小割及输出方案)
- 网络流24题:太空飞行计划问题
- 网络流二十四题之二 —— 太空飞行计划问题(SHUT)
- [网络流24题] 太空飞行计划问题
- 网络流24题2 太空飞行计划问题 洛谷 2762
- 线性规划与网络流24题の2 太空飞行计划问题(最大权闭合图问题)
- 网络流24题之T2 太空飞行计划问题
- 最大流——Luogu2762 [网络流24题]太空飞行计划问题
- 网络流24题 太空飞行计划问题___最大权闭合子图
- 太空飞行计划问题(网络流24题,七)
- 【网络流24题】 No.2 太空飞行计划问题 (最大闭合权图 最大流 )
- P2762 太空飞行计划问题(网络流24题之一)
- 线性规划与网络流24题 02太空飞行计划问题
- kyeremal-网络流24题T2-太空飞行计划问题