问题描述
W 教授正在为国家航天中心计划一系列的太空飞行。每次太空飞行可进行一系列商业 性实验而获取利润。现已确定了一个可供选择的实验集合E={E1,E2,…,Em},和进行这 些实验需要使用的全部仪器的集合I={I1,I2,…In}。实验Ej需要用到的仪器是I的子集RjI。 配置仪器Ik的费用为ck美元。实验Ej的赞助商已同意为该实验结果支付pj美元。W教授的 任务是找出一个有效算法,确定在一次太空飞行中要进行哪些实验并因此而配置哪些仪器才 能使太空飞行的净收益最大。这里净收益是指进行实验所获得的全部收入与配置仪器的全部 费用的差额。 编程任务 对于给定的实验和仪器配置情况,编程找出净收益最大的试验计划。
数据输入
文件第1行有2 个正整数m和n。m是实验数,n是仪器数。 接下来的m 行,每行是一个实验的有关数据。第一个数赞助商同意支付该实验的费用;接着是该实验需要用到的若干仪器的编号。最后一行的n个数是配置每个仪器的费用。
结果输出
最佳实验方案。第1 行是实验编号;第2行是仪器编号;最后一行是净收益。
输入样例
2 3
10 1 2
25 2 3
5 6 7
输出样例
1 2
1 2 3
17
限制
1<=n,m<=50
时间:1S
空间:256MB
题解
https://www.cnblogs.com/zhenghaotian/p/6929083.html
https://yq.aliyun.com/ziliao/290204
http://www.cnblogs.com/wuyiqi/archive/2012/03/12/2391960.html
残量网络中和源点连通的点的集合(不包括源点)即为选中的
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
const int N=150,M=50*50*4+105,inf=1047483647;
int n,m,s=101,t=102,ans;
int num=1,last[N],nxt[M],ver[M],c[M];
inline void add(int x,int y,int z)
{nxt[++num]=last[x]; last[x]=num; ver[num]=y; c[num]=z;
nxt[++num]=last[y]; last[y]=num; ver[num]=x; c[num]=0;
}
queue<int> q;int d[N],cur[N];
inline bool bfs()
{memset(d,0,sizeof(d));
while(!q.empty()) q.pop();
q.push(s); d[s]=1;
for(int i=1;i<=110;i++) cur[i]=last[i];
while(!q.empty())
{int x=q.front(); q.pop();
for(int i=last[x],y;i;i=nxt[i])
{if(!d[y=ver[i]] && c[i])
d[y]=d[x]+1,q.push(y);
}
}
return d[t]>0;
}
int dfs(int x,int flow)
{if(x==t) return flow;
int rest=flow;
for(int i=cur[x],y;i && rest;i=nxt[i])
{cur[x]=i; y=ver[i];
if(d[y]==d[x]+1 && c[i])
{int f=dfs(y,min(c[i],rest));
if(f==0) d[y]=0;
c[i]-=f; c[i^1]+=f;
rest-=f;
}
}
return flow-rest;
}
inline bool read(int &re)
{ re=0; char ch = getchar();
while (!('0'<= ch && ch<='9')) { if(ch == '\n') return 0; ch=getchar(); }
while ('0'<= ch && ch<='9') { re=re*10+ch-'0'; ch=getchar(); }
return ch!='\n';
}
int main()
{
scanf("%d%d",&m,&n); int r;
for(int i=1;i<=m;i++)
{scanf("%d",&r); ans+=r;
add(s,i,r);
while(read(r)) {add(i,r+50,inf);}
add(i,r+50,inf);
}
for(int i=1;i<=n;i++){scanf("%d",&r); add(i+50,t,r);}
while(bfs())
while(int flow=dfs(s,inf)) ans-=flow;
for(int i=1;i<=m;i++) if(d[i]) printf("%d ",i);
printf("\n");
for(int i=1;i<=n;i++) if(d[i+50]) printf("%d ",i);
printf("\n%d",ans);
return 0;
}