说实话,这题我也懵逼
就是一个玄学的最小割
源点--(实验收益)-->实验--(INF)-->器材--(器材成本)-->汇点
求出最小割后用所有收益减去,就是最大收益
就是这样
上代码:
#include<bits/stdc++.h>
#define o edge[i].t
using namespace std;
const int S=0,T=100000;
int head[101000],dep[101000];
int n,m,cnt=1,sum;
struct hh{int t,w,nxt;}edge[1001000];
void make_edge(int f,int t,int w)
{
edge[++cnt]=(hh){t,w,head[f]};
head[f]=cnt;
edge[++cnt]=(hh){f,0,head[t]};
head[t]=cnt;
}
int dfs(int x,int sum)
{
if (x==T) return sum;
int num=0;
for (int i=head[x];i;i=edge[i].nxt)
if (edge[i].w&&dep[o]==dep[x]+1)
{
int k=dfs(o,min(edge[i].w,sum));
sum-=k;
num+=k;
edge[i].w-=k;
edge[i^1].w+=k;
if (!sum) return num;
}
return num;
}
bool bfs()
{
queue<int>q;
q.push(S);
memset(dep,0,sizeof(dep));
dep[S]=1;
while (!q.empty())
{
int tmp=q.front();
q.pop();
for (int i=head[tmp];i;i=edge[i].nxt)
if (edge[i].w&&!dep[o])
{
dep[o]=dep[tmp]+1;
q.push(o);
}
}
return dep[T];
}
int dinic()
{
int ans=0;
while (bfs()) ans+=dfs(S,INT_MAX);
return ans;
}
int main()
{
int i,j,k,x,y,z;
scanf("%d %d",&n,&m);
for (i=1;i<=n;i++)
{
scanf("%d",&x);
sum+=x;
make_edge(S,i,x);
char ch=getchar();
while((ch=getchar())!='\n')//麻烦的读入
{
x=ch-'0';
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
make_edge(i,x+n,INT_MAX);
if(ch=='\n') break;
}
}
for (i=1;i<=m;i++) scanf("%d",&x),make_edge(i+n,T,x);
cout<<sum-dinic();
}
这是只输出最大收益的
要输出方案就再加几行