题意
给定n个实验,m个机器,选一个实验得到ai价值,选一个机器有bi代价,每一个实验必须要某些机器参与才能进行,问获得的最大价值
思路
对于每一个实验,分为两种选择:
-
选取这个实验,那么必须选取其对应的所有机器
-
不选这个实验,那么其对应的机器只受到其他实验选择的影响
也就是说在实验和机器中选择一部分“放弃”,使得总价值最大,考虑最小割
建两排点分别表示实验和机器,用权值为ai的边连接源点与实验,权值为bi的边连接机器与汇点,实验与其相关的机器连权值为INF的边,那么ans=sigma(ai)-最小割
通过这样建图就可以发现,由于中间连边为INF不可能被切掉,所以被切掉的边只能是实验或者它对应的所有机器
由于原题还需要输出方案,只需要输出最后一次bfs(即没有増广路)可以到达的实验以及其对应的机器即可
Code:
#include<bits/stdc++.h>
#define N 105
using namespace std;
const int INF = 2000000000;
int n,m,s=101,t=102,sum;
bool flag;
int dep[N];
struct Edge
{
int next,to,flow;
}edge[10005];int head[N],cur[N],cnt=1;
void add_edge(int from,int to,int flow)
{
edge[++cnt].next=head[from];
edge[cnt].to=to;
edge[cnt].flow=flow;
head[from]=cnt;
}
void add(int from,int to,int flow)
{
add_edge(from,to,flow);
add_edge(to,from,0);
}
int read()
{
char ch=' ';int res=0;
while(!isdigit(ch)) ch=getchar();
while(isdigit(ch)) res=res*10+ch-'0',ch=getchar();
if(ch=='
') flag=1;
return res;
}
bool bfs()
{
queue<int> q;
memset(dep,0,sizeof(dep));
for(int i=1;i<=104;++i) cur[i]=head[i];
q.push(s); dep[s]=1;
while(!q.empty())
{
int u=q.front();q.pop();
for(int i=head[u];i;i=edge[i].next)
{
int v=edge[i].to;
if(edge[i].flow<=0||dep[v]) continue;
dep[v]=dep[u]+1;
q.push(v);
if(v==t) return true;
}
}
return false;
}
int dfs(int rt,int rest)
{
if(rt==t) return rest;
int used=0;
for(int i=cur[rt];i;i=edge[i].next)
{
cur[rt]=i;
int v=edge[i].to;
if(dep[v]==dep[rt]+1&&edge[i].flow>0)
{
int k=dfs(v,min(edge[i].flow,rest-used));
if(!k) dep[v]=0;
edge[i].flow-=k;
edge[i^1].flow+=k;
used+=k;
}
}
return used;
}
int dinic()
{
int ret=0,flow=0;
while(bfs()) while((flow=dfs(s,INF))) ret+=flow;
return ret;
}
int main()
{
n=read();m=read();
for(int i=1;i<=n;++i)
{
int earn=read();flag=0;
sum+=earn;
add(s,i,earn);
while(!flag)
{
int ned=read();
add(i,ned+50,INF);
}
}
for(int i=1;i<=m;++i)
{
int cost=read();
add(i+50,t,cost);
}
int maxx=dinic();
for(int i=1;i<=50;++i) if(dep[i]) printf("%d ",i);
printf("
");
for(int i=1;i<=50;++i) if(dep[i+50]) printf("%d ",i);
printf("
");
printf("%d
",sum-maxx);
return 0;
}