首页 > 技术文章 > BZOJ 1497 最大获利(最大权闭合子图)

qzqzgfy 2016-06-12 19:28 原文

http://www.lydsy.com/JudgeOnline/problem.php?id=1497

思路:由题意可以得知,每个顾客都依赖2个中转站,那么让中转站连有向边到汇点,流量为它的建设费用,源点连到每个顾客,流量为赚的钱,然后每个顾客到它依赖的中转站连流量为inf的边

 1 #include<algorithm>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<iostream>
 6 #define inf 0x7fffffff
 7 int tot,go[500005],first[500005],next[500005],flow[500005];
 8 int op[500005],S,T,nodes,dis[500005],cnt[500005],n,m;
 9 int read(){
10     int t=0,f=1;char ch=getchar();
11     while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
12     while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();}
13     return t*f;
14 }
15 void insert(int x,int y,int z){
16     tot++;
17     go[tot]=y;
18     next[tot]=first[x];
19     first[x]=tot;
20     flow[tot]=z;
21 }
22 void add(int x,int y,int z){
23     insert(x,y,z);op[tot]=tot+1;
24     insert(y,x,0);op[tot]=tot-1;
25 }
26 int dfs(int x,int f){
27     if (x==T) return f;
28     int mn=nodes,sum=0;
29     for (int i=first[x];i;i=next[i]){
30         int pur=go[i];
31         if (flow[i]&&dis[pur]+1==dis[x]){
32             int save=dfs(pur,std::min(f-sum,flow[i]));
33             sum+=save;
34             flow[i]-=save;
35             flow[op[i]]+=save;
36             if (f==sum||dis[S]>=nodes) return sum;
37         }
38         if (flow[i]) mn=std::min(mn,dis[pur]); 
39     }
40     if (sum==0){
41         cnt[dis[x]]--;
42         if (cnt[dis[x]]==0){
43             dis[S]=nodes;
44         }
45         else{
46             dis[x]=mn+1;
47             cnt[dis[x]]++;
48         }
49     }
50     return sum;
51 }
52 int main(){
53     n=read(),m=read();
54     nodes=n+m+2;
55     T=n+m+1;S=0;
56     for (int i=1;i<=n;i++){
57      int x=read();
58      add(m+i,T,x);
59     }
60     int sum=0;
61     for (int i=1;i<=m;i++){
62         int x=read(),y=read(),z=read();
63         add(S,i,z);
64         add(i,x+m,inf);
65         add(i,y+m,inf);
66         sum+=z;
67     }
68     int ans=0;
69     while (dis[S]<nodes) ans+=dfs(S,inf);
70     printf("%d\n",std::max(sum-ans,0));
71 }

 

推荐阅读