太空飞行计划问题-最大权闭合图
题目描述
W 教授正在为国家航天中心计划一系列的太空飞行。每次太空飞行可进行一系列商业性实验而获取利润。现已确定了一个可供选择的实验集合E={E1,E2,…,Em},和进行这些实验需要使用的全部仪器的集合I={I1,I2,…In}。实验Ej需要用到的仪器是I的子集RjÍI。配置仪器Ik的费用为ck美元。实验Ej的赞助商已同意为该实验结果支付pj美元。W教授的任务是找出一个有效算法,确定在一次太空飞行中要进行哪些实验并因此而配置哪些仪器才能使太空飞行的净收益最大。这里净收益是指进行实验所获得的全部收入与配置仪器的全部费用的差额。
对于给定的实验和仪器配置情况,编程找出净收益最大的试验计划。
输入输出格式
输入格式:
第1行有2 个正整数m和n。m是实验数,n是仪器数。接下来的m 行,每行是一个实验的有关数据。第一个数赞助商同意支付该实验的费用;接着是该实验需要用到的若干仪器的编号。最后一行的n个数是配置每个仪器的费用。
输出格式:
第1 行是实验编号;第2行是仪器编号;最后一行是净收益。
输入输出样例
输入样例#1: 复制2 3 10 1 2 25 2 3 5 6 7输出样例#1: 复制
1 2 1 2 3 17
说明
感谢@FlierKing 提供spj
是最大权闭合图的裸题,是看了 胡伯涛《最小割模型在信息学竞赛中的应用》论文来的,上面对最大权闭合图的做法进行了证明,虽然我并没看太懂= =
做法就是建立S向实验点连边,cap为实验奖励,仪器点向T连边,cap为仪器费用,实验-仪器连边cap为inf然后跑最小割,答案就是所有实验的奖励总和减去这个最小割就是最大的净赚钱数。
最后输出方案的做法: 将dinic过的图从S开始dfs,能访问到的实验点就是方案中包含的实验。
我是这么理解的,净赚费用 = 实验总奖励 -(没有做的实验 + 仪器费用) ,使得括号内的费用最小答案就会最大了,对建好的图跑最小割,如果实验点最后仍与S连接说明没有割去这个实验,但是割去了这个实验所需的所有仪器。含义就是如果做某个实验是可以赚钱的就会割去他所需的仪器,如果是赔本的就会割去这个实验,正好对应了括号内的费用!
#include<bits/stdc++.h> using namespace std; #define inf 0x3f3f3f3f struct Edge{ int v,cap,flow,next; }e[100010]; int tot,first[110],S,T,N,M; int d[110],cur[110]; bool vis[110],vis2[110]; char tools[10000]; void add(int u,int v,int cap){ e[tot]=Edge{v,cap,0,first[u]}; first[u]=tot++; e[tot]=Edge{u,0,0,first[v]}; first[v]=tot++; } int bfs(){ memset(vis,0,sizeof(vis)); queue<int>q; q.push(S); vis[S]=1; d[S]=0; while(!q.empty()){ int u=q.front(); q.pop(); for(int i=first[u];~i;i=e[i].next){ if(!vis[e[i].v] && e[i].cap>e[i].flow){ d[e[i].v]=d[u]+1; vis[e[i].v]=1; q.push(e[i].v); } } } return vis[T]; } int dfs(int u,int a){ if(u==T || a==0)return a; int flow=0,f; for(int &i=cur[u];~i;i=e[i].next){ if(d[e[i].v]==d[u]+1 && (f=dfs(e[i].v,min(a,e[i].cap-e[i].flow)))>0){ e[i].flow+=f; e[i^1].flow-=f; flow+=f; a-=f; if(a==0)break; } } return flow; } int dinic(){ int ans=0; while(bfs()){ for(int i=0;i<=T;++i)cur[i]=first[i]; ans+=dfs(S,inf); } return ans; } void gao(int u){ vis[u]=1; for(int i=first[u];~i;i=e[i].next){ if(!vis[e[i].v] && e[i].cap>e[i].flow) gao(e[i].v); } } int main(){ while(scanf("%d%d",&M,&N)!=EOF){ int p,u,v,s=0; S=0,T=M+N+1; tot=0,memset(first,-1,sizeof(first)); for(int i=1;i<=M;++i){ scanf("%d",&p); add(0,i,p); s+=p; cin.getline(tools,10000); int len=0,tool; while(sscanf(tools+len,"%d",&tool)==1){ add(i,tool+M,inf); while(tool) tool/=10,len++; len++; } } for(int i=1;i<=N;++i){ scanf("%d",&p); add(i+M,T,p); } s=s-dinic(); memset(vis,0,sizeof(vis)); memset(vis2,0,sizeof(vis2)); gao(S); bool head=1; for(int i=1;i<=M;++i){ if(vis[i]){ if(head){ printf("%d",i); head=0; } else{ printf(" %d",i); } for(int j=first[i];~j;j=e[j].next) vis2[e[j].v-M]=1; } } puts(""); head=1; for(int i=1;i<=N;++i){ if(vis2[i]){ if(head){ printf("%d",i); head=0; } else printf(" %d",i); } } puts(""); cout<<s<<endl; } return 0; }
- 【网络流二十四题 太空飞行计划问题】【最大权闭合图->最小割】
- 线性规划与网络流24题の2 太空飞行计划问题(最大权闭合图问题)
- 网络流24题 太空飞行计划问题___最大权闭合子图
- 洛谷 P2762 太空飞行计划问题 【最大权闭合子图+最小割】
- 【网络流24题】 No.2 太空飞行计划问题 (最大闭合权图 最大流 )
- [SWUSTOJ1737] 太空飞行计划问题(最大权闭合子图,记录路径)
- 洛谷 P2762 太空飞行计划问题 P3410 拍照【最大权闭合子图】题解+代码
- [luoguP2762] 太空飞行计划问题(最大权闭合图—最小割—最大流)
- 【网络流24题】太空飞行计划(最大权闭合图+最小割)
- 线性规划与网络流24题之太空飞行计划 最大权闭合图
- 网络流24题之二 太空飞行计划 最大权闭合子图
- LOJ 「网络流 24 题」太空飞行计划(最大权闭合子图)
- 【网络流24题 太空飞行计划】最大权闭合子图
- LOJ 6001 太空飞行计划 (最大权闭合图+打印最小割)
- loj #6001. 「网络流 24 题」太空飞行计划(最大权闭合子图)
- [网络流24题] 02 太空飞行计划(最大权闭合图, 最大流)
- 网络流24题之太空飞行计划——最大权闭合子图
- ★ 太空飞行计划 最大权闭合图+输出方案
- 线性规划与网络流24题第2题 太空飞行计划 最大权闭合图
- 太空飞行计划问题(最大流)