1. 程式人生 > >[NOI2006]最大獲利——最大權閉合子圖

[NOI2006]最大獲利——最大權閉合子圖

amp r+ ios 入門 TE hellip 最優化 AS mem

題目描述

新的技術正沖擊著手機通訊市場,對於各大運營商來說,這既是機遇,更是挑戰。THU集團旗下的CS&T通訊公司在新一代通訊技術血戰的前夜,需要做太多的準備工作,僅就站址選擇一項,就需要完成前期市場研究、站址勘測、最優化等項目。在前期市場調查和站址勘測之後,公司得到了一共N個可以作為通訊信號中轉站的地址,而由於這些地址的地理位置差異,在不同的地方建造通訊中轉站需要投入的成本也是不一樣的,所幸在前期調查之後這些都是已知數據:建立第i個通訊中轉站需要的成本為Pi(1≤i≤N)。另外公司調查得出了所有期望中的用戶群,一共M個。關於第i個用戶群的信息概括為Ai, Bi和Ci:這些用戶會使用中轉站Ai和中轉站Bi進行通訊,公司可以獲益Ci。(1≤i≤M, 1≤Ai, Bi≤N) THU集團的CS&T公司可以有選擇的建立一些中轉站(投入成本),為一些用戶提供服務並獲得收益(獲益之和)。那麽如何選擇最終建立的中轉站才能讓公司的凈獲利最大呢?(凈獲利 = 獲益之和 - 投入成本之和)

輸入

輸入文件中第一行有兩個正整數N和M 。第二行中有N個整數描述每一個通訊中轉站的建立成本,依次為P1, P2, …, PN 。以下M行,第(i + 2)行的三個數Ai, Bi和Ci描述第i個用戶群的信息。所有變量的含義可以參見題目描述。

輸出

你的程序只要向輸出文件輸出一個整數,表示公司可以得到的最大凈獲利。

這道題是最大權閉合子圖入門題,源點連向用戶群,容量為收益;中轉站連向匯點,容量為成本。每個用戶群連向對應中轉站,容量為INF。求網絡最小割(最大流),用總收益減掉最小割即可。

  1 #include<cstdio>
  2
#include<algorithm> 3 #include<iostream> 4 #include<cmath> 5 #include<cstring> 6 using namespace std; 7 int head[60001]; 8 int to[400001]; 9 int val[400001]; 10 int next[400001]; 11 int tot=1; 12 int n,m; 13 int x; 14 int a,b,c; 15 int S,T; 16 int d[60001];
17 int q[60001]; 18 int INF=2147483647; 19 int ans=0; 20 int sum=0; 21 void add(int x,int y,int z) 22 { 23 tot++; 24 next[tot]=head[x]; 25 head[x]=tot; 26 to[tot]=y; 27 val[tot]=z; 28 tot++; 29 next[tot]=head[y]; 30 head[y]=tot; 31 to[tot]=x; 32 val[tot]=0; 33 } 34 int dfs(int x,int maxflow) 35 { 36 if(x==T) 37 { 38 return maxflow; 39 } 40 int used=0; 41 int nowflow; 42 for(int i=head[x];i;i=next[i]) 43 { 44 if(val[i]!=0&&d[to[i]]==d[x]+1) 45 { 46 nowflow=dfs(to[i],min(maxflow-used,val[i])); 47 val[i]-=nowflow; 48 val[i^1]+=nowflow; 49 used+=nowflow; 50 if(nowflow==maxflow) 51 { 52 return maxflow; 53 } 54 } 55 } 56 if(used==0) 57 { 58 d[x]=-1; 59 } 60 return used; 61 } 62 bool bfs(int S,int T) 63 { 64 memset(d,-1,sizeof(d)); 65 memset(q,0,sizeof(q)); 66 d[S]=0; 67 int l=0; 68 int r=0; 69 q[r++]=S; 70 while(l<r) 71 { 72 int now=q[l]; 73 for(int i=head[now];i;i=next[i]) 74 { 75 if(d[to[i]]==-1&&val[i]!=0) 76 { 77 d[to[i]]=d[now]+1; 78 q[r++]=to[i]; 79 } 80 } 81 l++; 82 } 83 if(d[T]!=-1) 84 { 85 return true; 86 } 87 return false; 88 } 89 void dinic() 90 { 91 while(bfs(S,T)==true) 92 { 93 ans+=dfs(S,INF); 94 } 95 } 96 int main() 97 { 98 scanf("%d%d",&n,&m); 99 S=n+m+1; 100 T=n+m+2; 101 for(int i=1;i<=n;i++) 102 { 103 scanf("%d",&x); 104 add(i+m,T,x); 105 } 106 for(int i=1;i<=m;i++) 107 { 108 scanf("%d%d%d",&a,&b,&c); 109 sum+=c; 110 add(S,i,c); 111 add(i,a+m,INF); 112 add(i,b+m,INF); 113 } 114 dinic(); 115 printf("%d",sum-ans); 116 }

[NOI2006]最大獲利——最大權閉合子圖