[NOI2006] 最大获利 (最大权闭合图)

来源:互联网 发布:金融大数据 pdf 编辑:程序博客网 时间:2024/05/16 09:10
 

                      [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\n",sum-ans);117     return 0;118 } 119 120 int hhh=hh();121 122 int main() {;}
题解

 

阅读全文
0 0
原创粉丝点击