[BZOJ1497][NOI2006]最大获利(最大权闭合子图)
2017-11-22 14:06
239 查看
原题链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1497
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。
一定要注意数组范围不要开小了!!我RE了很多次!!
此题是最大权闭合子图的裸题,最大权闭合子图的话可以看一看胡伯涛的论文结合这篇博客去理解,是基于网络流中最大流-最小割的一个应用,一般是处理一些带依赖关系的图。
对于这道题,我们可以发现在这个图里面,点带负权(其实是正权理解成负权),边带正权且边依赖点,那么答案就是MAX(∑w-∑p) (w是边权,p是点权),那么我们只要将边和点分开来建在一个图里面,然后求出这个图的最大权闭合子图即可。
这个图大概长这个样子:
![](http://img.blog.csdn.net/20171122135940823?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvQ0FCSV9aR1g=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
因为长度为INF的边是不可能成为割的,那么割左边,就代表我不选择这个点,不记上这个点的花费,如果割右边就代表我不选择这条边,不记上这条边的花费。
边还没有建完,对于点向ed建权值为pi的边,对于st到边建权值为ei的边,
这样正权和-最小割就是花费啦。(这也是求最大权闭合子图的思想)
这道题是被动地边依赖点,那么我们要围绕这个性质来建边。
code:
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。
一定要注意数组范围不要开小了!!我RE了很多次!!
此题是最大权闭合子图的裸题,最大权闭合子图的话可以看一看胡伯涛的论文结合这篇博客去理解,是基于网络流中最大流-最小割的一个应用,一般是处理一些带依赖关系的图。
对于这道题,我们可以发现在这个图里面,点带负权(其实是正权理解成负权),边带正权且边依赖点,那么答案就是MAX(∑w-∑p) (w是边权,p是点权),那么我们只要将边和点分开来建在一个图里面,然后求出这个图的最大权闭合子图即可。
这个图大概长这个样子:
因为长度为INF的边是不可能成为割的,那么割左边,就代表我不选择这个点,不记上这个点的花费,如果割右边就代表我不选择这条边,不记上这条边的花费。
边还没有建完,对于点向ed建权值为pi的边,对于st到边建权值为ei的边,
这样正权和-最小割就是花费啦。(这也是求最大权闭合子图的思想)
这道题是被动地边依赖点,那么我们要围绕这个性质来建边。
code:
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> using namespace std; const int maxn=110000; const int M=9999999; struct node { int x,y,c,next,other; }a[maxn*5]; int len,last[maxn*4]; int st,ed; inline void ins(int x,int y,int c) { int k1,k2; len++; k1=len; a[len].x=x;a[len].y=y;a[len].c=c; a[len].next=last[x];last[x]=len; len++; k2=len; a[len].x=y;a[len].y=x;a[len].c=0; a[len].next=last[y];last[y]=len; a[k1].other=k2; a[k2].other=k1; } int list[maxn*5],head,tail,h[maxn]; inline bool bfs() { memset(h,0,sizeof(h)); h[st]=1; list[1]=st,head=1,tail=2; while(head!=tail) { int x=list[head]; for(int k=last[x];k;k=a[k].next) { int y=a[k].y; if(a[k].c>0 && h[y]==0) { h[y]=h[x]+1; list[tail++]=y; } } head++; } if(h[ed]>0) return true; else return false; } inline int findflow(int x,int f) { if(x==ed) return f; int s=0,t; for(int k=last[x];k;k=a[k].next) { int y=a[k].y; if(a[k].c>0 && h[y]==h[x]+1 && s<f) { t=findflow(y,min(f-s,a[k].c)); s+=t; a[k].c-=t; a[a[k].other].c+=t; if(s==f) return s; } } if(s==0) h[x]=0; return s; } int dinic() { int s=0; while(bfs()) { s+=findflow(st,M); } return s; } int main() { int n,m; scanf("%d%d",&n,&m); memset(last,0,sizeof(last)); len=0; st=n+m+1,ed=st+1; for(int i=1;i<=n;i++) { int d;scanf("%d",&d); ins(i+m,ed,d); } int ans=0; for(int i=1;i<=m;i++) { int x,y,c;scanf("%d%d%d",&x,&y,&c); ans+=c; ins(st,i,c); ins(i,x+m,M); ins(i,y+m,M); } printf("%d\n",ans-dinic()); return 0; }
相关文章推荐
- 【BZOJ】1497: [NOI2006]最大获利 最大权闭合子图或最小割
- BZOJ 1497: [NOI2006]最大获利 最大权闭合子图
- bzoj 1497: [NOI2006]最大获利-----------算法模板[最大权闭合子图]&省选计划系列
- _bzoj1497 [NOI2006]最大获利【最大权闭合子图】
- 【BZOJ 1497】 [NOI2006]最大获利 最大权闭合子图
- BZOJ 1497 [NOI2006]最大获利 最大权闭合子图
- 【最大权闭合子图】BZOJ1497[NOI2006]-最大获利
- [BZOJ 1497][NOI 2006]最大获利(最大权闭合子图)
- bzoj 1497 [NOI2006]最大获利【最大权闭合子图+最小割】
- [BZOJ 1497][NOI2006]最大获利(最大权闭合图)
- BZOJ_1497_[NOI2006]_最大获利_(最大流+最大权闭合图)
- [bzoj1497][NOI2006]最大获利 最大闭合权子图
- 【bzoj1497】[NOI2006]最大获利 最大点权闭合图
- bzoj1497 [ NOI2006 ] --最大权闭合子图
- bzoj 1497: [NOI2006]最大获利 最小割 最大权闭和子图
- BZOJ 1497: [NOI2006]最大获利(最大权闭合图)
- 1497: [NOI2006]最大获利(最大权闭合子图)
- [bzoj1497]NOI2006最大获利(最大权封闭子图)
- 最大权闭合图 && 【BZOJ】1497: [NOI2006]最大获利
- BZOJ 1497: [NOI2006]最大获利 最大闭合权