• BZOJ1497 [NOI2006] 最大获利


    题目链接: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

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

    最大权闭合子图,参见2007年国家集训队胡伯涛论文《最小割模型在信息学竞赛中的应用》,参照论文中的方法建图

    源点向每一个中转站连流量为费用的边,用户向汇点连流量为收益的边,中转站向对应用户连流量为INF的边

    关于效率:

    参照这道题的实际表现改进了最大流模版的写法,BFS到汇点就跳出能快很多(这个图只有4层,且第三层的点很多),不同的当前弧优化姿势也能影响效率。最快的一份代码跑到了252ms。

    效率对比:400+ms是另一种当前弧优化的姿势,1000+ms是BFS到汇点不跳出。

    update: 后来对代码进行了几乎可以忽略的小修改,只快了4ms,要想提高效率估计只有写非递归DFS,或者干脆用ISAP了。但是单纯的提高效率并没有什么意义。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 #include <cstring>
     5 #include <queue>
     6 #define rep(i,l,r) for(int i=l; i<=r; i++)
     7 #define clr(x,y) memset(x,y,sizeof(x))
     8 #define travel(x) for(int i=last[x]; i!=-1; i=edge[i].pre)
     9 const int INF = 0x7fffffff;
    10 const int maxn = 55010;
    11 using namespace std;
    12 struct Edge{
    13     int pre,to,cost;
    14 }edge[350000];
    15 int n,m,x,y,z,s,t,now,tot=-1,ans=0,total=0,last[maxn],cur[maxn],d[maxn];
    16 queue <int> q;
    17 inline int read(){
    18     int ans = 0, f = 1;
    19     char c = getchar();
    20     while (!isdigit(c)){
    21         if (c == '-') f = -1;
    22         c = getchar();
    23     }
    24     while (isdigit(c)){
    25         ans = ans * 10 + c - '0';
    26         c = getchar();
    27     }
    28     return ans * f;
    29 }
    30 inline void addedge(int x,int y,int z){
    31     edge[++tot].pre = last[x];
    32     edge[tot].to = y;
    33     edge[tot].cost = z;
    34     last[x] = tot;
    35 }
    36 bool bfs(){
    37     while (!q.empty()) q.pop();
    38     clr(d,-1); d[s] = 0; q.push(s);
    39     while (!q.empty()){
    40         now = q.front(); q.pop();
    41         travel(now){
    42             if (d[edge[i].to] == -1 && edge[i].cost > 0){
    43                 d[edge[i].to] = d[now] + 1;
    44                 q.push(edge[i].to);
    45                 if (edge[i].to == t) return 1;
    46             }
    47         }
    48     }
    49     return 0;
    50 }
    51 int dfs(int x,int flow){
    52     if (x == t || (!flow)) return flow; int w = 0;
    53     for (int i=cur[x]; i!=-1 && w<flow; i=edge[i].pre){
    54         if (d[edge[i].to] == d[x] + 1 && edge[i].cost > 0){
    55             int delta = dfs(edge[i].to,min(flow-w,edge[i].cost));
    56             edge[i].cost -= delta;
    57             edge[i^1].cost += delta;
    58             w += delta;
    59             if (edge[i].cost) cur[x] = i;
    60         }
    61     }
    62     if (w < flow) d[x] = -1;
    63     return w;
    64 }
    65 int main(){
    66     n = read(); m = read(); clr(last,-1);
    67     s = 0; t = n + m + 1;
    68     rep(i,1,n){
    69         x = read();
    70         addedge(s,i,x); addedge(i,s,0);
    71     }
    72     rep(i,1,m){
    73         x = read(); y = read(); z = read();
    74         total += z;
    75         addedge(i+n,t,z); addedge(t,i+n,0);
    76         addedge(x,i+n,INF); addedge(i+n,x,0);
    77         addedge(y,i+n,INF); addedge(i+n,y,0);
    78     }
    79     while (bfs()){
    80         rep(i,0,n+m+1) cur[i] = last[i];
    81         int tans = dfs(s,INF);
    82         ans += tans;
    83     }
    84     printf("%d
    ",total-ans);
    85     return 0;
    86 }
    View Code
  • 相关阅读:
    个人报告04
    个人报告03
    构建之法阅读笔记07
    个人报告02
    第二次冲刺个人报告01
    第二阶段个人总结5
    第十三周学习进度情况
    第二阶段个人总结4(5.28)
    第二阶段个人总结3(5.27)
    课堂作业之找小水王
  • 原文地址:https://www.cnblogs.com/jimzeng/p/bzoj1497.html
Copyright © 2020-2023  润新知