VIJOS 最大获利 邻接表

来源:互联网 发布:如何注册手机淘宝 编辑:程序博客网 时间:2024/05/22 11:46

 

描述 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 Format  输入中第一行有两个正整数N 和M 。 
第二行中有 N 个整数描述每一个通讯中转站的建立成本,依次为P1, P2, …, PN 。 
以下 M 行,第(i + 2)行的三个数 Ai, Bi 和 Ci 描述第 i 个用户群的信息。 
所有变量的含义可以参见题目描述。       输出格式 Output Format  你的程序只要输出一个整数,表示公司可以得到的最大净获利。 
               样例输入 Sample Input         样例输出 Sample Output         时间限制 Time Limitation  各个测试点2s 
       注释 Hint  原题要求: 
只需要向输出文件输出一行,行内不得有多余空白字符,行末须有一个换行/回车符,格式不对不能得分。 
数据范围: 
80%的数据中:N≤200,M≤1 000。 
100%的数据中:N≤5 000,M≤50 000,0≤Ci≤100,0≤Pi≤100。       来源 Source  NOI 2006 Day2 第1题, 最大获利. 
题目文本从官方公布pdf获得, 数据由《年鉴》光盘获得. 

 

 

#include<stdio.h>

#include<string.h>

const int V=250001,E=250001;

struct edge

{

    int aim,cap;

    edge *next,*pair;

    edge() {}

    edge(int t,int c,edge *n):aim(t),cap(c),next(n) {}

    void* operator new(unsigned,void* p)

    {

        return p;

    }

}*e[V],Te[E+E],*Pe=Te;

int n,num[V],dis[V],s,t,m;

int augment(int u,int augc)

{

    if(u==t)return augc;

    int d,tmp=n-1;

    for(edge *i=e[u]; i; i=i->next)if(i->cap)

        {

            if(dis[u]==dis[i->aim]+1)

            {

                d=augment(i->aim,augc<i->cap?augc:i->cap);

                i->cap-=d,i->pair->cap+=d;

                if(d||dis[s]==n)return d;

            }

            if(dis[i->aim]<tmp)tmp=dis[i->aim];

        }

    if(!--num[dis[u]])dis[s]=n;

    num[dis[u]=tmp+1]++;

    return 0;

}

int main()

{

    memset(e,0,sizeof(e));

    scanf("%d%d",&n,&m);

for(int i=1;i<=n;i++)

{

   int x;

   scanf("%d",&x);

   e[1]=new(Pe++)edge(i+1,x,e[1]);

        e[i+1]=new(Pe++)edge(1,0,e[i+1]);

        e[1]->pair=e[i+1];

        e[i+1]->pair=e[1];

}

int sum=0;

for(int i=1;i<=m;i++)

{

int x, y, c;

scanf("%d%d%d", &x, &y, &c);

        e[x+1]=new(Pe++)edge(n+i+1,1<<30-1,e[x+1]);

        e[n+i+1]=new(Pe++)edge(x+1,0,e[n+i+1]);

        e[x+1]->pair=e[n+i+1];

        e[n+i+1]->pair=e[x+1];

        e[y+1]=new(Pe++)edge(n+i+1,1<<30-1,e[y+1]);

        e[n+i+1]=new(Pe++)edge(y+1,0,e[n+i+1]);

        e[y+1]->pair=e[n+i+1];

        e[n+i+1]->pair=e[y+1];

        e[n+i+1]=new(Pe++)edge(n+m+1+1,c,e[n+i+1]);

        e[n+m+1+1]=new(Pe++)edge(n+i+1,0,e[n+m+1+1]);

        e[n+i+1]->pair=e[n+m+1+1];

        e[n+m+1+1]->pair=e[n+i+1];

sum+=c;

}

n=n+m+2;

    memset(dis,0,sizeof(dis));

    memset(num,0,sizeof(num)),num[0]=n;

    int flow=0;

    s=1,t=n;

    while(dis[s]<n)flow+=augment(s,0xfffff);

    printf("%d/n",sum-flow);

    return 0;

}