Description 有N个工作,M种机器,每种机器你可以租或者买过来.
每个工作包括若干道工序,每道工序需要某种机器来完成,你可以通过购买或租用机器来完成。 现在给出这些参数,求最大利润 Input 第一行给出
N,M(1<=N<=1200,1<=M<=1200)
下面将有N块数据,每块数据第一行给出完成这个任务能赚到的钱(其在[1,5000])及有多少道工序
接下来若干行每行两个数,分别描述完成工序所需要的机器编号及租用它的费用(其在[1,20000])
最后M行,每行给出购买机器的费用(其在[1,20000]) Output 最大利润
裸的最大权闭合子图需要在收益和要求间连正无穷的边,代表不能割断。只需要改成租用的花费即可。
dinic需要当前弧优化。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int s=10005,t=10006,oo=0x3f3f3f3f;
int fir[10010],ne[4000010],to[4000010],w[4000010],
f[10010],que[10010],cur[10010],
n,m,num;
int rd()
{
int x=0;
char c=getchar();
while (c<'0'||c>'9') c=getchar();
while (c>='0'&&c<='9')
{
x=x*10+c-'0';
c=getchar();
}
return x;
}
void add(int u,int v,int x)
{
num++;
ne[num*2]=fir[u];
fir[u]=num*2;
to[num*2]=v;
w[num*2]=x;
ne[num*2+1]=fir[v];
fir[v]=num*2+1;
to[num*2+1]=u;
w[num*2+1]=0;
}
bool bfs()
{
int u,v,hd=1,tl=1;
for (int i=1;i<=n+m;i++) f[i]=0;
f[t]=0;
f[s]=1;
que[1]=s;
while (hd<=tl)
{
u=que[hd++];
for (int i=fir[u];i;i=ne[i])
if (!f[v=to[i]]&&w[i])
{
f[v]=f[u]+1;
que[++tl]=v;
}
}
for (int i=1;i<=m+n;i++) cur[i]=fir[i];
cur[s]=fir[s];
cur[t]=fir[t];
return f[t];
}
int dfs(int u,int lim)
{
int v,x,ret=0;
if (u==t) return lim;
for (int i=cur[u];i&&ret<lim;i=ne[i])
if (f[v=to[i]]==f[u]+1&&w[i])
{
x=dfs(v,min(lim-ret,w[i]));
ret+=x;
w[i]-=x;
if (w[i]) cur[u]=i;
w[i^1]+=x;
}
if (!ret) f[u]=0;
return ret;
}
int main()
{
int ans=0,x,y,z,u;
n=rd();
m=rd();
for (int i=1;i<=n;i++)
{
x=rd();
y=rd();
ans+=x;
add(s,i,x);
while (y--)
{
u=rd();
z=rd();
add(i,u+n,z);
}
}
for (int i=1;i<=m;i++)
add(i+n,t,rd());
while (bfs()) ans-=dfs(s,oo);
printf("%d\n",ans);
}