题目描述:
有N个工作,M种机器,每种机器你可以租或者买过来.每个工作包括若干道工序,每道工序需要某种机器来完成,你可以通过购买或租用机器来完成。现在给出这些参数,求最大利润
解析:
这道题一看就是最大权闭合子图,如果不考虑可以购买这种操作,那和太空飞行计划那道题是一样的了。考虑到购买一件机器后就不用再租用它,那么我们只要在机器和汇点之间连一条流量为购买费用的边,其他边正常构建,用总的利益减去最小割即可。
代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#define inf 0x7fffffff
using namespace std;
int T,n,m,cnt=1,ans,cur[2501],q[2505],head[2505],h[2505];
struct data{int to,next,v;}e[3000001];
void ins(int u,int v,int w)
{cnt++;e[cnt].to=v;e[cnt].v=w;e[cnt].next=head[u];head[u]=cnt;}
void insert(int u,int v,int w)
{ins(u,v,w);ins(v,u,0);}
bool bfs()
{
int t=0,w=1,i,now;
for(int i=1;i<=T;i++)h[i]=-1;
q[0]=h[0]=0;
while(t!=w)
{
now=q[t];t++;if(t==2501)t=0;
for(i=head[now];i;i=e[i].next)
{
if(e[i].v&&h[e[i].to]<0)
{h[e[i].to]=h[now]+1;q[w++]=e[i].to;if(w==2501)w=0;}
}
}
if(h[T]==-1)return 0;return 1;
}
int dfs(int x,int f)
{
if(x==T)return f;
int w,used=0;
for(int i=cur[x];i;i=e[i].next)
{
if(e[i].v&&h[e[i].to]==h[x]+1)
{
w=f-used;
w=dfs(e[i].to,min(w,e[i].v));
e[i].v-=w;if(e[i].v>0)cur[x]=i;e[i^1].v+=w;
used+=w;if(used==f)return f;
}
}
if(!used)h[x]=-1;
return used;
}
void dinic(){while(bfs()){for(int i=0;i<=T;i++)cur[i]=head[i];ans-=dfs(0,inf);}}
int main()
{
scanf("%d%d",&n,&m);
T=n+m+1;
int a,b,c,d;
for(int i=1;i<=n;i++)
{
scanf("%d%d",&a,&b);
insert(0,i,a);ans+=a;
for(int j=1;j<=b;j++)
{
scanf("%d%d",&c,&d);
insert(i,n+c,d);
}
}
for(int i=1;i<=m;i++)
{
scanf("%d",&a);
insert(n+i,T,a);
}
dinic();
printf("%d",ans);
return 0;
}