bzoj1497 [NOI2006]最大獲利

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。【評分方法】本題沒有部分分,你的程序的輸出只有和我們的答案完全一致才能獲得滿分,否則不得分。【數據規模和約定】 80%的數據中:N≤200,M≤1 000。 100%的數據中:N≤5 000,M≤50 000,0≤Ci≤100,0≤Pi≤100。


正解:最大流

將題意轉化爲圖論模型,從源點到每個用戶羣連一條ci的邊,從每個中轉站到匯點連一條pi的邊,從每個用戶羣到對應的中轉站連一條inf的邊,那麼沒有使用的中轉站成本+沒有獲利的用戶羣利潤就是最小割,所以ans=∑ci-maxflow。


#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#define il inline
#define RG register
#define ll long long
#define inf (1<<30)


using namespace std;

struct edge{ int nt,to,flow,cap; }g[320010];

int head[60010],q[60010],d[60010],vis[60010],n,m,tot,num=1;

il int gi(){
    RG int x=0,q=1; RG char ch=getchar(); while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
    if (ch=='-') q=-1,ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x;
}

il void insert(RG int from,RG int to,RG int cap){ g[++num]=(edge){head[from],to,0,cap},head[from]=num; return; }

il int bfs(RG int st,RG int ed){
    memset(vis,0,sizeof(vis));
    RG int h=0,t=1; q[t]=st,d[st]=0,vis[st]=1;
    while (h<t){
	RG int x=q[++h];
	for (RG int i=head[x];i;i=g[i].nt){
	    RG int v=g[i].to;
	    if (!vis[v] && g[i].cap>g[i].flow)
		q[++t]=v,d[v]=d[x]+1,vis[v]=1;
	}
    }
    return vis[ed];
}

il int dfs(RG int x,RG int ed,RG int a){
    if (x==ed || a==0) return a;
    RG int flow=0,f;
    for (RG int i=head[x];i;i=g[i].nt){
	RG int v=g[i].to;
	if (d[x]+1==d[v] && (f=dfs(v,ed,min(a,g[i].cap-g[i].flow)))>0){
	    g[i].flow+=f,g[i^1].flow-=f,flow+=f,a-=f; if (!a) break;
	}
    }
    return flow;
}

il int dinic(){
    RG int flow=0;
    while (bfs(n+m+1,n+m+2)) flow+=dfs(n+m+1,n+m+2,inf);
    return flow;
}

il void work(){
    n=gi(),m=gi(); RG int p;
    for (RG int i=1;i<=n;++i) p=gi(),insert(m+i,n+m+2,p),insert(n+m+2,m+i,0);
    for (RG int i=1;i<=m;++i){
	RG int a=gi(),b=gi(),c=gi(); tot+=c;
	insert(n+m+1,i,c),insert(i,n+m+1,0);
	insert(i,m+a,inf),insert(m+a,i,0);
	insert(i,m+b,inf),insert(m+b,i,0);
    }
    printf("%d\n",tot-dinic()); return;
}

int main(){
    freopen("profit.in","r",stdin);
    freopen("profit.out","w",stdout);
    work();
    return 0;
}


發佈了49 篇原創文章 · 獲贊 0 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章