zoukankan      html  css  js  c++  java
  • [NOI2006] 最大获利 (最大权闭合图)

                          [NOI2006] 最大获利 

    【问题描述】

        新的技术正冲击着手机通讯市场,对于各大运营商来说,这既是机遇,更是挑战。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 个用户群的信息。 
    所有变量的含义可以参见题目描述。

    【输出文件】

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

    【样例输入】

    profit.in

    5 5 
    1 2 3 4 5 
    1 2 3 
    2 3 4 
    1 3 3 
    1 4 2 
    4 5 3

    【样例输出】

    profit.out

    4

    【样例说明】

    选择建立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 /*
      2     在cogs上跑了一个rank3 !
      3     跑最大权闭合图 
      4     用 dinic
      5     建图 建立一个源点 连向 n个站点 权值为费用 
      6     m个客户连向汇点 权值为利润 
      7     其他边之间流量为 INF 
      8     跑出最大流 即为不选择建造的站点和不选用户 而损失的利益
      9     总利益减去就好了 
     10 */
     11 #include<queue>
     12 #include<cstdio>
     13 #include<cstring> 
     14 #include<iostream>
     15 #define MAXN 500010
     16 #define INF 0x7fffffff 
     17 
     18 using namespace std;
     19 
     20 struct node {
     21     int to;
     22     int next;
     23     int v;
     24 };
     25 node e[MAXN];
     26 
     27 int head[MAXN<<1],tot=1;
     28 
     29 int n,m,sum,ans,a,b,v,p,src,decc;
     30 
     31 int depth[MAXN<<1],cur[MAXN<<1];
     32 
     33 queue<int> q;
     34 
     35 inline void read(int&x) {
     36     int f=1;x=0;char c=getchar();
     37     while(c>'9'||c<'0') {if(c=='-') f=-1;c=getchar();}
     38     while(c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-48;c=getchar();}
     39     x=x*f;
     40 }
     41 
     42 inline void add(int x,int y,int z) {
     43     e[++tot].to=y;
     44     e[tot].v=z;
     45     e[tot].next=head[x];
     46     head[x]=tot;
     47 }
     48 
     49 inline void add_edge(int x,int y,int z) {
     50     add(x,y,z);
     51     add(y,x,0);
     52 }
     53 
     54 bool bfs() {
     55     for(int i=0;i<=decc;i++) cur[i]=head[i],depth[i]=-1; 
     56     while(!q.empty()) q.pop();
     57     q.push(src);
     58     depth[src]=0;
     59     while(!q.empty()) {
     60         int u=q.front();
     61         q.pop();
     62         for(int i=head[u];i!=-1;i=e[i].next) {
     63             int to=e[i].to;
     64             if(e[i].v&&depth[to]==-1) {
     65                 q.push(to);
     66                 depth[to]=depth[u]+1;
     67                 if(to==decc) return true;
     68             }
     69         }
     70     }
     71     return false;
     72 }
     73 
     74 int dfs(int now,int flow) {
     75     if(now==decc) return flow;
     76     int rest=0,delat;
     77     for(int &i=cur[now];i!=-1;i=e[i].next) {
     78         int to=e[i].to;
     79         if(e[i].v&&depth[to]==depth[now]+1) {
     80             delat=dfs(to,min(e[i].v,flow-rest));
     81             if(delat) {
     82                 e[i].v-=delat;
     83                 e[i^1].v+=delat;
     84                 rest+=delat;
     85                 if(rest==flow) break;
     86             }
     87         }
     88     }
     89     if(flow!=rest) depth[now]=-1;
     90     return rest;
     91 }
     92 
     93 inline void dinic() {
     94     while(bfs()) 
     95       ans+=dfs(src,INF);
     96 }
     97 
     98 int hh() {
     99     freopen("profit.in","r",stdin);
    100     freopen("profit.out","w",stdout);
    101     read(n);read(m);
    102     src=0;decc=n+m+1;
    103     memset(head,-1,sizeof head);
    104     for(int i=1;i<=n;i++) {
    105         read(p);
    106         add_edge(src,i,p);
    107     }
    108     for(int i=1;i<=m;i++) {
    109         read(a);read(b);read(v);
    110         add_edge(a,n+i,INF);
    111         add_edge(b,n+i,INF);
    112         add_edge(n+i,decc,v);
    113         sum+=v;
    114     }
    115     dinic();
    116     printf("%d
    ",sum-ans);
    117     return 0;
    118 } 
    119 
    120 int hhh=hh();
    121 
    122 int main() {;}
    题解


    作者:乌鸦坐飞机
    出处:http://www.cnblogs.com/whistle13326/
    新的风暴已经出现 怎么能够停止不前 穿越时空 竭尽全力 我会来到你身边 微笑面对危险 梦想成真不会遥远 鼓起勇气 坚定向前 奇迹一定会出现

     
  • 相关阅读:
    Search for a Range 分类: Leetcode(查找) Leetcode(排序) 2015-04-10 15:34 23人阅读 评论(0) 收藏
    First Missing Positive 分类: Leetcode(排序) 2015-04-09 17:13 25人阅读 评论(0) 收藏
    Insertion Sort List 分类: Leetcode(排序) 2015-04-09 11:26 23人阅读 评论(0) 收藏
    Merge k Sorted Lists 分类: Leetcode(树) 2015-04-09 09:35 17人阅读 评论(0) 收藏
    Merge Two Sorted Lists 分类: Leetcode(排序) 2015-04-08 21:59 24人阅读 评论(0) 收藏
    Merge Sorted Array 分类: Leetcode(排序) 2015-04-08 21:52 24人阅读 评论(0) 收藏
    Sum Root to Leaf Numbers 分类: Leetcode(树) 2015-04-04 21:25 27人阅读 评论(0) 收藏
    计算机网络数据链路层次学习
    ArrayList总结及部分源码分析
    抽象类基本概念
  • 原文地址:https://www.cnblogs.com/whistle13326/p/7325773.html
Copyright © 2011-2022 走看看