太空飞行计划问题
题目描述
W 教授正在为国家航天中心计划一系列的太空飞行。每次太空飞行可进行一系列商业性实验而获取利润。现已确定了一个可供选择的实验集合E={E1,E2,…,Em},和进行这些实验需要使用的全部仪器的集合I={I1,I2,…In}。实验Ej需要用到的仪器是I的子集Rj。 配置仪器Ik的费用为ck美元。实验Ej的赞助商已同意为该实验结果支付pj美元。W教授的任务是找出一个有效算法,确定在一次太空飞行中要进行哪些实验并因此而配置哪些仪器才能使太空飞行的净收益最大。这里净收益是指进行实验所获得的全部收入与配置仪器的全部费用的差额。
«编程任务:
对于给定的实验和仪器配置情况,编程找出净收益最大的试验计划。
«编程任务:
对于给定的实验和仪器配置情况,编程找出净收益最大的试验计划。
输入
由文件input.txt提供输入数据。文件第1行有2 个正整数m和n。m是实验数,n是仪器数。接下来的m 行,每行是一个实验的有关数据。第一个数赞助商同意支付该实验的费用;接着是该实验需要用到的若干仪器的编号。最后一行的n个数是配置每个仪器的费用。
输出
程序运行结束时,将最佳实验方案输出到文件output.txt 中。第1 行是实验编号;第2行是仪器编号;最后一行是净收益。
样例输入
2 3
10 1 2
25 2 3
5 6 7
样例输出
1 2
1 2 3
17
题意:不多说。
分析:最大流=最小割,净收益=所有资助费用-最小割。只要利润不为负的实验都要做,都要输出来。
#include<stdio.h> #include<string.h> #include<vector> #include<sstream> #include<queue> #include<algorithm> #define maxn 1000 #define inf 0x7fffffff using namespace std; struct edge { int from,to,cap,flow; }; vector<edge> edges; vector<int> G[maxn]; int d[maxn],cur[maxn]; bool vis[maxn]; int s,t; void init() { for(int i=0;i<maxn;i++) G[i].clear(); edges.clear(); } void add(int from,int to,int cap) { edges.push_back((edge){from,to,cap,0}); edges.push_back((edge){to,from,0,0}); int m=edges.size(); G[from].push_back(m-2); G[to].push_back(m-1); } bool bfs() { memset(vis,false,sizeof(vis)); memset(d,0,sizeof(d)); queue<int> q; q.push(s); d[s]=0,vis[s]=true; while(!q.empty()) { int x=q.front(); q.pop(); for(int i=0;i<G[x].size();i++) { edge& e=edges[G[x][i]]; if(!vis[e.to]&&e.cap>e.flow) { vis[e.to]=true; d[e.to]=d[x]+1; q.push(e.to); } } } return vis[t]; } int dfs(int x,int a) { if(x==t||a==0) return a; int flow=0,f; for(int& i=cur[x];i<G[x].size();i++) { edge& e=edges[G[x][i]]; if(d[x]+1==d[e.to]&&(f=dfs(e.to,min(a,e.cap-e.flow)))>0) { e.flow+=f; edges[G[x][i]^1].flow-=f; flow+=f; a-=f; if(a==0) break; } } return flow; } int maxflow() { int flow=0; while(bfs()) { memset(cur,0,sizeof(cur)); flow+=dfs(s,inf); } return flow; } bool fg[400]; int cnt[300]; char sss[300]; int main() { int m,n; while(scanf("%d%d",&m,&n)==2) { int c,x,y; init(); s=0,t=m+n+1; int sum=0; memset(cnt,0,sizeof(cnt)); for(int i=1;i<=m;i++) { scanf("%d",&c); sum+=c; add(s,i,c); getchar(); gets(sss); stringstream ss(sss); while(ss>>x) { cnt[i]++; add(i,x+m,inf); } } for(int i=1;i<=n;i++) { scanf("%d",&c); add(i+m,t,c); } int ans=maxflow(); memset(fg,false,sizeof(fg)); for(int i=m+1;i<=n+m;i++) { for(int j=0;j<G[i].size();j++) { edge& e=edges[G[i][j]]; if(e.from>e.to||e.to!=t||e.cap==inf) continue; for(int k=0;k<edges.size();k++) { int u=edges[k].from,v=edges[k].to; if(u>v) continue; edges[k].flow=edges[k^1].flow=0; edges[k^1].cap=0; } int tem=e.cap; e.cap=0; int me=maxflow(); e.cap=tem; if(ans-me==tem) fg[e.from]=true; } } for(int i=m+1;i<=n+m;i++) { if(!fg[i]) continue; for(int j=0;j<G[i].size();j++) { edge e=edges[G[i][j]]; if(e.to==t) continue; cnt[e.to]--; } } for(int i=1;i<=m;i++) if(!cnt[i]) printf("%d ",i); puts(""); for(int i=m+1;i<=n+m;i++) if(fg[i]) printf("%d ",i-m); puts(""); printf("%d\n",sum-ans); } return 0; }