Bzoj 1391: [Ceoi2008]order 网络流,最大权闭合图

1391: [Ceoi2008]order

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 1105  Solved: 331
[Submit][Status][Discuss]

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

Bzoj 1391: [Ceoi2008]order  网络流,最大权闭合图

Source

 
[Submit][Status][Discuss]

题解:

最大权闭合图。

又忘了咋连边了。。。QAQ

最大权闭合图:

    构造一个原点S,汇点T。S -> 权值为正的点  连一条容量为权值的边。权值为负的点 -> T  连一条容量为权值的绝对值的边。原图中的边连INF。

但本题中有可以租的机器,每一次租也要花费代价。考虑最大权闭合图中的原图的边连INF的意义:使边的两个顶点必须同时选。但这道题可以不选但要付出代价,所以将原图中的边连容量为租的花费。

注意:一定要加 当前弧优化 。。。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define MAXN 2520
 4 #define INF 1e9
 5 struct node
 6 {
 7     int begin,end,value,next;
 8 }edge[2884810];
 9 int cnt,Head[MAXN],q[MAXN],dis[MAXN],cur[MAXN],S,T;
10 void addedge(int bb,int ee,int vv)
11 {
12     edge[++cnt].begin=bb;edge[cnt].end=ee;edge[cnt].value=vv;edge[cnt].next=Head[bb];Head[bb]=cnt;
13 }
14 void addedge1(int bb,int ee,int vv)
15 {
16     addedge(bb,ee,vv);addedge(ee,bb,0);
17 }
18 int read()
19 {
20     int s=0,fh=1;char ch=getchar();
21     while(ch<'0'||ch>'9'){if(ch=='-')fh=-1;ch=getchar();}
22     while(ch>='0'&&ch<='9'){s=s*10+(ch-'0');ch=getchar();}
23     return s*fh;
24 }
25 int BFS()
26 {
27     int head,tail,u,v,i;
28     head=0;tail=1;q[tail]=S;
29     memset(dis,-1,sizeof(dis));dis[S]=0;
30     while(head!=tail)
31     {
32         head++;if(head==2510)head=0;
33         u=q[head];
34         for(i=Head[u];i!=-1;i=edge[i].next)
35         {
36             v=edge[i].end;
37             if(edge[i].value>0&&dis[v]<0)
38             {
39                 dis[v]=dis[u]+1;
40                 tail++;if(tail==2510)tail=0;
41                 q[tail]=v;
42             }
43         }
44     }
45     if(dis[T]<=0)return 0;
46     else return 1;
47 }
48 int DFS(int u,int minflow)
49 {
50     int used=0,ans,v,i;
51     if(u==T)return minflow;
52     for(i=cur[u];i!=-1;i=edge[i].next)
53     {
54         v=edge[i].end;
55         if(edge[i].value>0&&dis[v]==dis[u]+1)
56         {
57             ans=minflow-used;
58             ans=DFS(v,min(ans,edge[i].value));
59             edge[i].value-=ans;if(edge[i].value>0)cur[u]=i;
60             edge[i^1].value+=ans;
61             used+=ans;
62             if(used==minflow)return minflow;
63         }
64     }
65     if(used==0)dis[u]=-1;
66     return used;
67 }
68 int Dinic()
69 {
70     int maxflow=0,ans=0,i;
71     while(BFS()){for(i=1;i<=T;i++)cur[i]=Head[i];ans=DFS(S,INF);if(ans==0)break;maxflow+=ans;}
72     return maxflow;
73 }
74 int main()
75 {
76     int ans=0,n,m,s1,s2,s3,s4,s5,i,j;
77     n=read();m=read();
78     S=n+m+1;T=S+1;
79     memset(Head,-1,sizeof(Head));cnt=1;
80     for(i=1;i<=n;i++)
81     {
82         s1=read();s2=read();
83         addedge1(S,i,s1);ans+=s1;
84         for(j=1;j<=s2;j++)
85         {
86             s3=read();s4=read();
87             addedge1(i,s3+n,s4);
88         }
89     }
90     for(i=1;i<=m;i++){s5=read();addedge1(n+i,T,s5);}
91     printf("%d",ans-Dinic());
92     return 0;
93 }