[JZOJ2224] 【NOI2006】最大获利

来源:互联网 发布:各版 任盈盈 知乎 编辑:程序博客网 时间:2024/04/29 05:36

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公司可以有选择的建立一些中转站(投入成本),为一些用户提供服务并获得收益(获益之和)。那么如何选择最终建立的中转站才能让公司的净获利最大呢?(净获利 = 获益之和 - 投入成本之和)

【数据规模和约定】
  80%的数据中:N≤200,M≤1 000。
  100%的数据中:N≤5 000,M≤50 000,0≤Ci≤100,0≤Pi≤100。

Solution

想必这道题人人都知道,最大权闭合图的模板题~

每个用户群和每个基站建议点,用户群向依赖的基站连边,显然最大权闭合图是答案

最大权闭合图?看这里

P.S.:这题要用Dinic,用GAP会被卡

Code

#include<cstdio>#include<cstdlib>#include<algorithm>#include<iostream>#include<cstring>#include<cmath>#define fo(i,a,b) for(i=a;i<=b;i++)#define fod(i,a,b) for(i=a;i>=b;i--)#define LL long long#define N 60000#define M 500000#define INF 2000000000using namespace std;int n,m,nt[M],lt[M],fs[M],dt[M],zs[M],f[M],st,ed,m1,h[N],d[M];void fx(){    zs[m1]=m1-1;    zs[m1-1]=m1;}void link(int x,int y,int z){    d[++m1]=y;    f[m1]=z;    if (fs[x]==0) fs[x]=m1;    lt[x]=nt[lt[x]]=m1;}void mt(int x,int y,int z){    link(x,y,z);    link(y,x,0);    fx();}bool bfs(){    memset(h,0,sizeof(h));    int i=0,j=1,k,p,l;    dt[j]=st;    h[st]=1;    while (i<j)    {        k=dt[++i];        for(l=fs[k];l>0;l=nt[l])        {            p=d[l];            if (f[l]>0&&h[p]==0) dt[++j]=p,h[p]=h[k]+1;         }    }    return h[ed]>0;}int dinic(int k,int s){    int i,p,l=0,sl=0;    if(k==ed) return s;    for(i=fs[k];i>0;i=nt[i])    {        p=d[i];        if (f[i]>0&&h[p]==h[k]+1)        {            l=dinic(p,min(s,f[i]));            if (l>0)            {                sl+=l;                s-=l;                f[i]-=l;                f[zs[i]]+=l;                if (s==0) break;            }        }    }    if (sl==0) h[k]=-1;    return sl;}int main(){    cin>>n>>m;    st=n+m+1;    ed=n+m+2;    m1=0;    int i;    fo(i,1,n)     {        int p;        scanf("%d",&p);        mt(m+i,ed,p);    }    int s=0;    fo(i,1,m)    {        int x,y,z;        scanf("%d%d%d",&x,&y,&z);        s+=z;        mt(st,i,z);        mt(i,x+m,INF);        mt(i,y+m,INF);    }    while (bfs())         s-=dinic(st,INF);    cout<<s;}
0 0
原创粉丝点击