zoukankan      html  css  js  c++  java
  • 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
    ",ans - dinic());
    94     }
    95     return 0;
    96 }
    View Code
  • 相关阅读:
    通过修改配置文件修改MySQL的时区设置
    五子棋输赢判定算法
    windows下通过压缩包安装MySQL
    systemctl命令详解
    普通用户从其他主机连接MySQL数据库
    ubuntu普通用户使用wireshark的权限问题
    账号管理文件/etc/passwd和/etc/shadow
    为什么处理有序数组比无序数组快?
    一些图像处理函数用法
    基于C++求两个数的最大公约数最小公倍数
  • 原文地址:https://www.cnblogs.com/crackpotisback/p/4053656.html
Copyright © 2011-2022 走看看