1497: [NOI2006]最大獲利 Time Limit: 5 Sec Memory Limit: 64 MB Description 新的技術正沖擊著手機通訊市場,對于各大運營商來說,這既是機遇,更是挑戰。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公司可以有選擇的建立一些中轉站(投入成本),為一些用戶提供服務并獲得收益(獲益之和)。那么如何選擇最終建立的中轉站才能讓公司的凈獲利最大呢?(凈獲利 = 獲益之和 - 投入成本之和) Input 輸入文件中第一行有兩個正整數N和M 。第二行中有N個整數描述每一個通訊中轉站的建立成本,依次為P1, P2, …, PN 。以下M行,第(i + 2)行的三個數Ai, Bi和Ci描述第i個用戶群的信息。所有變量的含義可以參見題目描述。 Output 你的程序只要向輸出文件輸出一個整數,表示公司可以得到的最大凈獲利。 Sample Input 5 5 1 2 3 4 5 1 2 3 2 3 4 1 3 3 1 4 2 4 5 3 Sample Output 4 HINT 【樣例說明】選擇建立1、2、3號中轉站,則需要投入成本6,獲利為10,因此得到最大收益4?!驹u分方法】本題沒有部分分,你的程序的輸出只有和我們的答案完全一致才能獲得滿分,否則不得分?!緮祿幠:图s定】 80%的數據中:N≤200,M≤1 000。 100%的數據中:N≤5 000,M≤50 000,0≤Ci≤100,0≤Pi≤100。
/*最大權閉合子圖.這題建圖考慮逆向思維.邊化點,邊權為點權.我們認為理想答案為∑wi,然而這顯然是不可能的.那么ans的減少只來源于兩個部分.case 1:中轉站的花費.case 2:客戶貢獻的減少.先從源點向每個中轉站連邊,流量為a[i],割掉這條邊表示選擇了這個中轉站.然后每個中轉站向所涉及客戶連一條流量為INF的邊.然后從每個客戶向匯點連一條流量為INF的邊保證圖聯通. 最后從每個客戶向匯點連一條流量為wi的邊,割掉這條邊表示放棄了這個客戶.然后dinic跑最小割orz.*/#include<iostream>#include<cstring>#include<cstdio>#include<queue>#define MAXN 100001#define INF 1e9using namespace std;int S,T,n,m,ans,cut=1,tot,a[MAXN],dis[MAXN],head[MAXN];struct data{int u,v,next,c;}e[MAXN*5];queue<int>q;int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar(); return x*f;}void add(int u,int v,int x){ e[++cut].v=v;e[cut].u=u;e[cut].c=x;e[cut].next=head[u];head[u]=cut; e[++cut].v=u;e[cut].u=v;e[cut].c=0;e[cut].next=head[v];head[v]=cut;}bool bfs(){ memset(dis,-1,sizeof dis); q.push(0);dis[0]=0; while(!q.empty()) { int u=q.front();q.pop(); for(int i=head[u];i;i=e[i].next) { int v=e[i].v; if(dis[v]==-1&&e[i].c) dis[v]=dis[u]+1,q.push(v); } } return dis[T]!=-1;}int dfs(int u,int y){ if(u==T) return y; int rest=0; for(int i=head[u];i&&rest<y;i=e[i].next) { int v=e[i].v; if(dis[v]==dis[u]+1&&e[i].c) { int x=dfs(v,min(e[i].c,y-rest)); rest+=x; e[i].c-=x; e[i^1].c+=x; } } if(!rest) dis[u]=-1; return rest;}void dinic(){ while(bfs()) ans-=dfs(S,INF); return ;}int main(){ freopen("新聞熱點
疑難解答