zoukankan      html  css  js  c++  java
  • HDU 3879 && BZOJ 1497:Base Station && 最大获利 (最大权闭合图)

    http://acm.hdu.edu.cn/showproblem.php?pid=3879

    http://www.lydsy.com/JudgeOnline/problem.php?id=1497

    题意:给出n个点m条边,其中每个点有一个权值代表修建这个点需要耗费的钱,然后m条边里面,代表如果两个修建好的点相连的话,那么可以得到一点利润。求最大的获利。

    思路:和BZOJ 1497是同一道题目。学习最大权闭合图的题目,看了一下不清楚应该怎么建图,然后只好搜一个论文来看看。http://wenku.baidu.com/view/6507a6fe2cc58bd63186bdaf.html

    建图:将S与n个点相连,权值为点权,将m条边当成点与T相连,权值为边权,边的两个顶点分别再和化成点的边相连,权值为INF。

    闭合图可以解决一些依赖关系,例如这道题目需要有两个顶点才可以得到一条边,边是依赖于两个顶点的形成的。

    于是网络是这样的:S->站的点->边的点->T。

    我们对这个网络得到的一个割 = 选择的站的花费 + 未选择的边的利润(也可以看作损失的利润),显然这个割集越小越好,即最小割。我们要求的是答案 = 选择的边的利润 - 选择的站的利润。

    那么我们一开始可以先累加得到一个选择所有边的利润tot,那么恰好tot - 最小割 = 选择所有边的利润 - 未选择边的利润 - 选择的站的花费 = 选择的边的利润 - 选择的站的利润 = 答案。

    所以跑一遍最大流后就用tot - 最大流就可以得到答案了。

    记得边的数组要开大一点。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #include <queue>
     5 using namespace std;
     6 #define INF 0x3f3f3f3f
     7 #define N 60010
     8 #define M 350010 // 30w不过
     9 struct Edge {
    10     int u, v, nxt, cap;
    11     Edge () {}
    12     Edge (int u, int v, int nxt, int cap) : u(u), v(v), nxt(nxt), cap(cap) {}
    13 } edge[M];
    14 int head[N], tot, S, T, cur[N], dis[N], gap[N], pre[N];
    15 
    16 void Add(int u, int v, int cap) {
    17     edge[tot] = Edge(u, v, head[u], cap); head[u] = tot++;
    18     edge[tot] = Edge(v, u, head[v], 0); head[v] = tot++;
    19 }
    20 
    21 void BFS() {
    22     queue<int> que;
    23     que.push(T);
    24     memset(dis, INF, sizeof(dis));
    25     memset(gap, 0, sizeof(gap));
    26     gap[0]++; dis[T] = 0;
    27     while(!que.empty()) {
    28         int u = que.front(); que.pop();
    29         for(int i = head[u]; ~i; i = edge[i].nxt) {
    30             if(dis[edge[i].v] != INF) continue;
    31             dis[edge[i].v] = dis[u] + 1;
    32             gap[dis[edge[i].v]]++;
    33             que.push(edge[i].v);
    34         }
    35     }
    36 }
    37 
    38 int ISAP(int n) {
    39     BFS();
    40     memcpy(cur, head, sizeof(cur));
    41     int u = pre[S] = S, flow, ans = 0, index, i;
    42     while(dis[S] < n) {
    43         if(u == T) {
    44             flow = INF;
    45             for(i = S; i != T; i = edge[cur[i]].v)
    46                 if(flow > edge[cur[i]].cap) flow = edge[cur[i]].cap, index = i;
    47             for(i = S; i != T; i = edge[cur[i]].v)
    48                 edge[cur[i]].cap -= flow, edge[cur[i]^1].cap += flow;
    49             u = index; ans += flow;
    50         }
    51         for(i = cur[u]; ~i; i = edge[i].nxt) if(edge[i].cap && dis[edge[i].v] + 1 == dis[u]) break;
    52         if(~i) { cur[u] = i; pre[edge[i].v] = u; u = edge[i].v; }
    53         else {
    54             if(--gap[dis[u]] == 0) break;
    55             int md = n + 1;
    56             for(i = head[u]; ~i; i = edge[i].nxt)
    57                 if(edge[i].cap && dis[edge[i].v] < md) md = dis[edge[i].v], cur[u] = i;
    58             gap[dis[u] = md + 1]++;
    59             u = pre[u];
    60         }
    61     }
    62     return ans;
    63 }
    64 
    65 int main() {
    66     int n, m;
    67     while(~scanf("%d%d", &n, &m)) {
    68         memset(head, -1, sizeof(head));
    69         tot = 0; S = 0; T = n + m + 1;
    70         for(int i = 1; i <= n; i++) {
    71             int w; scanf("%d", &w);
    72             Add(S, i, w); // 源点和站点相连
    73         }
    74         int tot = 0;
    75         for(int i = 1; i <= m; i++) {
    76             int a, b, c;
    77             scanf("%d%d%d",&a, &b, &c);
    78             tot += c; // 选择边的利润和
    79             Add(i + n, T, c); // 边的点和汇点相连
    80             Add(a, i + n, INF);
    81             Add(b, i + n, INF);
    82         }
    83         printf("%d
    ", tot - ISAP(T + 1));
    84     }
    85     return 0;
    86 }
  • 相关阅读:
    tuple 元组及字典dict
    day 49 css属性补充浮动 属性定位 抽屉作业
    day48 选择器(基本、层级 、属性) css属性
    day47 列表 表单 css初识
    day 46 http和html
    day 45索引
    day 44 练习题讲解 多表查询
    day 40 多表查询 子查询
    day39 表之间的关联关系、 补充 表操作总结 where 、group by、
    day38 数据类型 约束条件
  • 原文地址:https://www.cnblogs.com/fightfordream/p/6354259.html
Copyright © 2011-2022 走看看