题目
题解
关于题意,并不是很清楚一个实验如果不赚不亏要不要选 (spj是因为这个地方吗???)
建图就是将所有实验与源点相连,容量为收益;所有仪器与汇点相连,容量为价格;再将实验与所需仪器相连,容量为inf;将所有实验的收益相加减去跑出的最大流,得到的就是净收益
至于记录方案,我也不是很懂,可以看看[http://blog.csdn.net/slyz_wumingshi/article/details/62228040](http://blog.csdn.net/slyz_wumingshi/article/details/62228040
代码
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdio>
#define N 40005
#define inf 2000000000
#define ll long long
using namespace std;
int m,n,s,t,ans[N];
ll sum,cost;
bool flag[N];
struct node
{
int to,nt;
ll cap;
}E[N];
int num=1,p[N];
void add(int x,int y,ll v)
{
E[++num].to=y;E[num].cap=v;
E[num].nt=p[x];p[x]=num;
E[++num].to=x;E[num].cap=0;
E[num].nt=p[y];p[y]=num;
}
int d[N],q[N];
bool bfs()
{
memset(d,-1,sizeof(d));
int head=0,tail=0;
q[++tail]=s;d[s]=0;
while(head<tail)
{
int k=q[++head];
for(int e=p[k];e;e=E[e].nt)
{
int kk=E[e].to;
if(d[kk]==-1&&E[e].cap)
{
d[kk]=d[k]+1;
q[++tail]=kk;
flag[kk]=1;
}
}
}
return d[t]>=0;
}
ll dfs(int x,ll f)
{
memset(flag,0,sizeof(flag));
if(x==t) return f;
for(int e=p[x];e;e=E[e].nt)
{
int k=E[e].to;
if(d[k]==d[x]+1&&E[e].cap)
{
ll ff=dfs(k,min(E[e].cap,f));
if(ff)
{
E[e].cap-=ff;
E[e^1].cap+=ff;
return ff;
}
}
}
return 0;
}
int main()
{
scanf("%d%d",&m,&n);
s=0;t=m+n+1;
for(int i=1;i<=m;i++)
{
int v,x=0;scanf("%d",&v);
add(s,i,v);sum+=v;
char ch;scanf("%c",&ch);
while(ch!=10)
{
if(ch==' ')
{
if(x) add(i,x+m,inf),x=0;
}
else x=x*10+ch-'0';
scanf("%c",&ch);
}
add(i,x+m,inf);
}
for(int i=1;i<=n;i++)
{
int c;scanf("%d",&c);
add(m+i,t,c);
}
while(bfs())
{
ll f;
while(f=dfs(s,inf)) cost+=f;
}
for(int i=1;i<=m;i++)
if(flag[i]) printf("%d ",i);
printf("
");ans[0]=0;
for(int i=m+1;i<=m+n;i++)
if(flag[i]) printf("%d ",i-m);
printf("
%lld",sum-cost);
return 0;
}