CodeVS 1789 最大获利

1789 最大获利

 

2006年NOI全国竞赛

 时间限制: 2 s
 空间限制: 128000 KB
 题目等级 : 大师 Master
 
 
 
题目描述 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 Description

输入文件中第一行有两个正整数 N 和 M 。 第二行中有 N 个整数描述每一个通讯中转站的建立成本,依次为 P1, P2, …, PN 。 以下 M 行,第(i + 2)行的三个数 Ai, Bi和 Ci描述第 i 个用户群的信息。 所有变量的含义可以参见题目描述。

输出描述 Output Description

你的程序只要向输出文件输出一个整数,表示公司可以得到的最大净获利。

样例输入 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

数据范围及提示 Data Size & 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。 

 

解题:最大权闭合子图

 1 #include <iostream>

 2 #include <cstdio>

 3 #include <cstring>

 4 #include <cmath>

 5 #include <algorithm>

 6 #include <climits>

 7 #include <vector>

 8 #include <queue>

 9 #include <cstdlib>

10 #include <string>

11 #include <set>

12 #include <stack>

13 #define LL long long

14 #define pii pair<int,int>

15 #define INF 0x3f3f3f3f

16 using namespace std;

17 const int maxn = 60000;

18 struct arc{

19     int to,flow,next;

20     arc(int x = 0,int y = 0,int z = -1){

21         to = x;

22         flow = y;

23         next = z;

24     }

25 };

26 arc e[1000000];

27 int head[maxn],d[maxn],cur[maxn];

28 int tot,S,T,n,m;

29 void add(int u,int v,int flow){

30     e[tot] = arc(v,flow,head[u]);

31     head[u] = tot++;

32     e[tot] = arc(u,0,head[v]);

33     head[v] = tot++;

34 }

35 bool bfs(){

36     memset(d,-1,sizeof(d));

37     d[S] = 1;

38     queue<int>q;

39     q.push(S);

40     while(!q.empty()){

41         int u = q.front();

42         q.pop();

43         for(int i = head[u]; ~i; i = e[i].next){

44             if(e[i].flow && d[e[i].to] == -1){

45                 d[e[i].to] = d[u] + 1;

46                 q.push(e[i].to);

47             }

48         }

49     }

50     return d[T] > -1;

51 }

52 int dfs(int u,int low){

53     if(u == T) return low;

54     int tmp = 0,a;

55     for(int &i = cur[u]; ~i; i = e[i].next){

56         if(e[i].flow && d[e[i].to] == d[u] + 1&&(a=dfs(e[i].to,min(low,e[i].flow)))){

57             e[i].flow -= a;

58             e[i^1].flow += a;

59             tmp += a;

60             low -= a;

61             if(!low) break;

62         }

63     }

64     if(!tmp) d[u] = -1;

65     return tmp;

66 }

67 int dinic(){

68     int ans = 0;

69     while(bfs()){

70         memcpy(cur,head,sizeof(head));

71         ans += dfs(S,INF);

72     }

73     return ans;

74 }

75 int main() {

76     int u,v,w;

77     while(~scanf("%d %d",&n,&m)){

78         memset(head,-1,sizeof(head));

79         S = tot = 0;

80         T = n + m + 1;

81         int ans = 0;

82         for(int i = 1; i <= n; ++i){

83             scanf("%d",&w);

84             add(i,T,w);

85         }

86         for(int i = 0; i < m; ++i){

87             scanf("%d %d %d",&u,&v,&w);

88             add(n+i+1,u,INF);

89             add(n+i+1,v,INF);

90             add(S,n+i+1,w);

91             ans += w;

92         }

93         printf("%d\n",ans - dinic());

94     }

95     return 0;

96 }
View Code

 

你可能感兴趣的:(code)