• bzoj 1497 最大获利


    新的技术正冲击着手机通讯市场,对于各大运营商来说,这既是机遇,更是挑战。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。


      当要从一个用户获得收益那么就得选择相应的中转站,很像最大权闭合图,于是思考按照它的方法来建图。

      用户代表的点和源点连边,容量为对应的收益,中转站代表的点和汇点连边,容量为对应的成本。用户i需要哪两个中转站,点i就向这个中转站连边,容量为无限大。

      稍微解释一下这个网络。考虑用户和源点之间的边。当它被割掉了,说明满足这个用户可能收益和成本(只是对于这个用户来说)相等,或者从他这儿得到收益结果会是亏本。如果它没有被割掉,容量和流量的差就是从它这儿得到的收益。

      所以最终的答案是收益的总和 - 最小割容量 = 收益的总和 - 最大流流量

    Code

      1 /**
      2  * bzoj
      3  * Problem#1497
      4  * Accepted
      5  * Time:746ms
      6  * Memory:14412k
      7  */
      8 #include <iostream>
      9 #include <cstdio>
     10 #include <ctime>
     11 #include <cctype>
     12 #include <cstring>
     13 #include <cstdlib>
     14 #include <fstream>
     15 #include <sstream>
     16 #include <algorithm>
     17 #include <map>
     18 #include <set>
     19 #include <stack>
     20 #include <queue>
     21 #include <vector>
     22 #include <stack>
     23 using namespace std;
     24 typedef bool boolean;
     25 #define inf 0xfffffff
     26 #define smin(a, b) a = min(a, b)
     27 #define smax(a, b) a = max(a, b)
     28 #define max3(a, b, c) max(a, max(b, c))
     29 #define min3(a, b, c) min(a, min(b, c))
     30 template<typename T>
     31 inline boolean readInteger(T& u){
     32     char x;
     33     int aFlag = 1;
     34     while(!isdigit((x = getchar())) && x != '-' && x != -1);
     35     if(x == -1) {
     36         ungetc(x, stdin);
     37         return false;
     38     }
     39     if(x == '-'){
     40         x = getchar();
     41         aFlag = -1;
     42     }
     43     for(u = x - '0'; isdigit((x = getchar())); u = (u << 1) + (u << 3) + x - '0');
     44     ungetc(x, stdin);
     45     u *= aFlag;
     46     return true;
     47 }
     48 
     49 template<typename T>class Matrix{
     50     public:
     51         T *p;
     52         int lines;
     53         int rows;
     54         Matrix():p(NULL){    }
     55         Matrix(int rows, int lines):lines(lines), rows(rows){
     56             p = new T[(lines * rows)];
     57         }
     58         T* operator [](int pos){
     59             return (p + pos * lines);
     60         }
     61 };
     62 #define matset(m, i, s) memset((m).p, (i), (s) * (m).lines * (m).rows)
     63 
     64 typedef class Edge {
     65     public:
     66         int end;
     67         int next;
     68         int flow;
     69         int cap;
     70         Edge(int end = 0, int next = -1, int flow = 0, int cap = 0):end(end), next(next), flow(flow), cap(cap) {    }
     71 }Edge;
     72 
     73 typedef class MapManager {
     74     public:
     75         int ce;
     76         vector<Edge> edge;
     77         int* h;
     78         
     79         MapManager():ce(0), h(NULL) {        }
     80         MapManager(int nodes):ce(0) {
     81             h = new int[(const int)(nodes + 1)];
     82             memset(h, -1, sizeof(int) * (nodes + 1));
     83         }
     84         
     85         inline void addEdge(int from, int end, int flow, int cap) {
     86             edge.push_back(Edge(end, h[from], flow, cap));
     87             h[from] = ce++;
     88         }
     89         
     90         inline void addDoubleEdge(int from, int end, int cap) {
     91             if(cap == 0)    return;
     92             addEdge(from, end, 0, cap);
     93             addEdge(end, from, cap, cap);
     94         }
     95         
     96         Edge& operator [] (int pos) {
     97             return edge[pos];
     98         }
     99 }MapManager;
    100 #define m_begin(g, i) (g).h[(i)]
    101 #define m_endpos -1
    102 
    103 typedef class Point {
    104     public:
    105         int x;
    106         int y;
    107         Point(int x = 0, int y = 0):x(x), y(y) {        }
    108 }Point;
    109 
    110 int n, m;
    111 int* p;
    112 int *a, *b, *c;
    113 MapManager g;
    114 
    115 int s, t;
    116 
    117 inline void init() {
    118     readInteger(n);
    119     readInteger(m);
    120     p = new int[(const int)(n + 1)];
    121     a = new int[(const int)(m + 1)];
    122     b = new int[(const int)(m + 1)];
    123     c = new int[(const int)(m + 1)];
    124     for(int i = 1; i <= n; i++)
    125         readInteger(p[i]);
    126     for(int i = 1; i <= m; i++) {
    127         readInteger(a[i]);
    128         readInteger(b[i]);
    129         readInteger(c[i]);
    130     }
    131 }
    132 
    133 int sum = 0;
    134 inline void init_map() {
    135     s = 0, t = n + m + 1;
    136     g = MapManager(t);
    137     for(int i = 1; i <= m; i++) {
    138         g.addDoubleEdge(s, i, c[i]);
    139         g.addDoubleEdge(i, a[i] + m, inf);
    140         g.addDoubleEdge(i, b[i] + m, inf);
    141         sum += c[i];
    142     }
    143     for(int i = 1; i <= n; i++)
    144         g.addDoubleEdge(i + m, t, p[i]);
    145 }
    146 
    147 int* dis;
    148 boolean* vis;
    149 queue<int> que;
    150 inline boolean bfs() {
    151     memset(vis, false, sizeof(boolean) * (t + 3));
    152     que.push(s);
    153     vis[s] = true;
    154     dis[s] = 0;
    155     while(!que.empty()) {
    156         int e = que.front();
    157         que.pop();
    158         for(int i = m_begin(g, e); i != m_endpos; i = g[i].next) {
    159             if(g[i].cap == g[i].flow)    continue;
    160             int eu = g[i].end;
    161             if(vis[eu])    continue;
    162             vis[eu] = true;
    163             dis[eu] = dis[e] + 1;
    164             que.push(eu);
    165         }
    166     }
    167     return vis[t];
    168 }
    169 
    170 int *cur;
    171 inline int blockedflow(int node, int minf) {
    172     if((node == t) || (minf == 0))    return minf;
    173     int f, flow = 0;
    174     for(int& i = cur[node]; i != m_endpos; i = g[i].next) {
    175         int& eu = g[i].end;
    176         if(dis[eu] == dis[node] + 1 && g[i].flow < g[i].cap && (f = blockedflow(eu, min(minf, g[i].cap - g[i].flow))) > 0) {
    177             minf -= f;
    178             flow += f;
    179             g[i].flow += f;
    180             g[i ^ 1].flow -= f;
    181             if(minf == 0)    return flow;
    182         }
    183     }
    184     return flow;
    185 }
    186 
    187 inline void init_dinic() {
    188     vis = new boolean[(const int)(t + 3)];
    189     dis = new int[(const int)(t + 3)];
    190     cur = new int[(const int)(t + 3)];
    191 }
    192 
    193 inline int dinic() {
    194     int maxflow = 0;
    195     while(bfs()) {
    196         for(int i = 0; i <= t; i++)
    197             cur[i] = m_begin(g, i);
    198         maxflow += blockedflow(s, inf);
    199     }
    200     return maxflow;
    201 }
    202 
    203 inline void solve() {
    204     printf("%d
    ", sum - dinic());
    205 }
    206 
    207 int main() {
    208     init();
    209     init_map();
    210     init_dinic();
    211     solve();
    212     return 0;
    213 }
  • 相关阅读:
    good course Very
    HTTP Hypertext Transfer Protocol Overview
    Linux下tar.xz结尾的文件的解压方法
    原来java HttpURLConnection本身就提供了chunk的支持,又是让人一惊啊
    牛人一枚
    V2EX › 花了3个晚上,把readability最新的1.7.1转成了python版的
    13.11. 惯例优先原则(convention over configuration)
    明尼苏达大学
    快速构建实时抓取集群 « 搜索技术博客-淘宝
    Java Practices > Home
  • 原文地址:https://www.cnblogs.com/yyf0309/p/7101767.html
Copyright © 2020-2023  润新知