BZOJ 1497 最大获利(最大权闭合子图)
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 }