zoukankan      html  css  js  c++  java
  • HDU 3061:Battle(最大权闭合图)

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

    题意:中文题意。

    思路:和上一题神似啊,比上一题还简单,重新看了遍论文让我对这个理解更加深了。

    闭合图:如果某个点在图中的话,那么这个点的后继点全部都要在图中。

    对应至题目,这里的必须攻占b以后才能攻占a,那么是a依赖于b。如果a在图中的话,那么b必定在图中(因为a是依赖于b的),所以是a连向b(而不是b连向a)。

    这里总结一下做最大权闭合图的套路:把权值为正的点与超级源点S相连,容量为该权值,把权值为负的点与超级汇点T相连,容量为该权值的绝对值,然后点与点之间的连边是,如果a依赖于b,那么a连一条边向b,容量为INF。如果要求删除的点数的话,从S开始DFS,残余网络中的点即删除的点。因为删除的点的集合是从S出发可以达到的并且不能达到T的点集(即割分成的两个集(S集和T集)的S集)。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <queue>
     4 #include <algorithm>
     5 using namespace std;
     6 #define N 510
     7 #define INF 0x3f3f3f3f
     8 typedef long long LL;
     9 struct Edge {
    10     int v, nxt, cap;
    11 } edge[500010];
    12 int head[N], cur[N], dis[N], pre[N], gap[N], vis[N], S, T, tot;
    13 
    14 void Add(int u, int v, int cap) {
    15     edge[tot] = (Edge) {v, head[u], cap}; head[u] = tot++;
    16     edge[tot] = (Edge) {u, head[v], 0}; head[v] = tot++;
    17 }
    18 
    19 int BFS() {
    20     memset(dis, INF, sizeof(dis));
    21     memset(gap, 0, sizeof(gap));
    22     queue<int> que; que.push(T);
    23     dis[T] = 0; gap[0]++;
    24     while(!que.empty()) {
    25         int u = que.front(); que.pop();
    26         for(int i = head[u]; ~i; i = edge[i].nxt) {
    27             int v = edge[i].v;
    28             if(dis[v] < INF) continue;
    29             dis[v] = dis[u] + 1;
    30             gap[dis[v]]++;
    31             que.push(v);
    32         }
    33     }
    34 }
    35 
    36 LL ISAP(int n) {
    37     BFS();
    38     memcpy(cur, head, sizeof(cur));
    39     int u = pre[S] = S, i, flow, index; LL ans = 0;
    40     while(dis[S] < n) {
    41         if(u == T) {
    42             flow = INF;
    43             for(i = S; i != T; i = edge[cur[i]].v)
    44                 if(flow > edge[cur[i]].cap) flow = edge[cur[i]].cap, index = i;
    45             for(i = S; i != T; i = edge[cur[i]].v)
    46                 edge[cur[i]].cap -= flow, edge[cur[i]^1].cap += flow;
    47             u = index; ans += flow;
    48         }
    49         for(i = cur[u]; ~i; i = edge[i].nxt) if(edge[i].cap > 0 && dis[edge[i].v] + 1 == dis[u]) break;
    50         if(~i) {
    51             cur[u] = i; pre[edge[i].v] = u; u = edge[i].v;
    52         } else {
    53             int md = n + 1;
    54             if(--gap[dis[u]] == 0) break;
    55             for(i = head[u]; ~i; i = edge[i].nxt)
    56                 if(edge[i].cap > 0 && dis[edge[i].v] < md) md = dis[edge[i].v], cur[u] = i;
    57             gap[dis[u] = md + 1]++;
    58             u = pre[u];
    59         }
    60     }
    61     return ans;
    62 }
    63 
    64 int main() {
    65     int n, m;
    66     while(~scanf("%d%d", &n, &m)) {
    67         S = 0, T = n + 1;
    68         LL sum = 0; int u, v; tot = 0;
    69         memset(head, -1, sizeof(head));
    70         memset(vis, 0, sizeof(vis));
    71         for(int i = 1; i <= n; i++) {
    72             int w; scanf("%d", &w);
    73             if(w > 0) Add(S, i, w), sum += w;
    74             else Add(i, T, -w);
    75         }
    76         for(int i = 1; i <= m; i++) {
    77             int u, v;
    78             scanf("%d%d", &u, &v);
    79             Add(u, v, INF);
    80         }
    81         LL ans = ISAP(T + 1);
    82         printf("%lld
    ", sum - ans);
    83     }
    84     return 0;
    85 }
  • 相关阅读:
    Android异步操作总结
    datatable1.9 与datatable1.10以数据差异
    ftk学习记录(形成全屏幕套件)
    linux处置服务Iptables
    Linux课程---9、安装RPM包(RPM的全称是什么)
    Linux课程---8、Linux启动流程
    Linux课程---7、shell技巧(获取帮助命令)
    Linux课程---6、别名管理和网络配置(Linux命令如何记)
    Linux课程---5、常用文件命令和目录命令(创建文件命令)
    英语发音规则---L字母
  • 原文地址:https://www.cnblogs.com/fightfordream/p/6371987.html
Copyright © 2011-2022 走看看