[最小割] Bzoj P1391 order

Description

有N个工作,M种机器,每种机器你可以租或者买过来. 每个工作包括若干道工序,每道工序需要某种机器来完成,你可以通过购买或租用机器来完成。 现在给出这些参数,求最大利润

Input

第一行给出 N,M(1<=N<=1200,1<=M<=1200) 下面将有N块数据,每块数据第一行给出完成这个任务能赚到的钱(其在[1,5000])及有多少道工序 接下来若干行每行两个数,分别描述完成工序所需要的机器编号及租用它的费用(其在[1,20000]) 最后M行,每行给出购买机器的费用(其在[1,20000])

Output

最大利润

Sample Input

2 3
100 2
1 30
2 20
100 2
1 40
3 80
50
80
110

Sample Output

50

HINT

 

题解

  • 如果一台机器只能买的话,就是一个经典的最大权闭合子图问题
  • s到每台机器连流量为花费的边,每台机器到依赖它的项目连流量为inf的边,每个项目到t连流量为收益的边
  • 所有项目收益总和-最小割就是答案
  • 那如果机器可以租呢? 只要把机器连向项目的边的流量改为租机器的流量就好了
  • 注意,要当前弧优化

代码

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <cstring>
 4 #include <algorithm>
 5 #define inf 1000000000
 6 using namespace std;
 7 int ans,tot,n,m,T,cnt=1,Q[30005],head[30005],state[30005],cur[30005];
 8 struct edge{ int to,from,v; }e[3000005];
 9 void insert(int x,int y,int v)
10 {
11     e[++cnt].to=y,e[cnt].from=head[x],head[x]=cnt,e[cnt].v=v;
12     e[++cnt].to=x,e[cnt].from=head[y],head[y]=cnt,e[cnt].v=0;
13 }
14 bool bfs()
15 {
16     int p=0,q=1;
17     memset(state,-1,sizeof(state));
18     state[0]=Q[0]=0;
19     while (p!=q)
20     {
21         int u=Q[p]; p++; if (p==2501) p=0;
22         for (int i=head[u];i;i=e[i].from) if (e[i].v&&state[e[i].to]==-1) state[e[i].to]=state[u]+1,Q[q++]=e[i].to,q=(q==2501)?0:q;
23     }
24     return state[T]!=-1;
25 }
26 int dfs(int x,int maxf)
27 {
28     if (x==T) return maxf;
29     int f=0,r;
30     for (int i=cur[x];i;i=e[i].from)
31         if (e[i].v&&state[e[i].to]==state[x]+1)
32         {
33             r=dfs(e[i].to,min(e[i].v,maxf-f)),e[i].v-=r,e[i^1].v+=r,f+=r;
34             if (e[i].v>0) cur[x]=i;
35             if (f==maxf) return f;
36         }
37     if (!f) state[x]=-1;
38     return f;
39 }
40 void dinic() { while (bfs()) for (int i=0;i<=T;i++) cur[i]=head[i],ans-=dfs(0,inf); }
41 int main()
42 {
43     scanf("%d%d",&n,&m),T=n+m+1;
44     for (int i=1,x,y;i<=n;i++)
45     {
46         scanf("%d%d",&x,&y),insert(0,i,x),ans+=x;
47         for (int j=1,l,r;j<=y;j++) scanf("%d%d",&l,&r),insert(i,n+l,r);
48     }
49     for (int i=1,x;i<=m;i++) scanf("%d",&x),insert(n+i,T,x);
50     dinic();
51     printf("%d",ans);
52 }

 

posted @ 2019-07-09 14:58 BEYang_Z 阅读(...) 评论(...) 编辑 收藏