zoukankan      html  css  js  c++  java
  • POJ 2987:Firing(最大权闭合图)

    http://poj.org/problem?id=2987

    题意:有公司要裁员,每裁一个人可以得到收益(有正有负),而且如果裁掉的这个人有党羽的话,必须将这个人的所有党羽都裁除,问最少的裁员人数是多少和最大收益是多少。

    思路:有依赖关系,最大权闭合图。我们要得到最大收益,那么就是尽量选择更多收益为正数的人,选择更少收益为负数的人,因此我们将收益为正数的人与源点连一条边,将收益为负数的人与汇点连一条边,这样得到的割集就是未选择的收益为正数的人+选择的收益为负数的人(也可以是损失的收益),很明显答案要使这个割集越小越好,那么就是求最小割。我们能够得到的最大收益是所有正数的和sum,我们再用sum-最小割(损失的收益)就可以得到最大收益了。

    至于最少的裁员人数,我也挺迷糊的。看到别人的“将从S出发能到达的点看做firing的集合中的点,其他的能到T的点看作不被firing的集合中的点,那么在做完最大流之后自然就不会有firing集合中的点指向不被firing的集合中的点的边了,否则就会形成增广路。”这句话后,似乎我们只要在最终的残余网络中,只要能从S遍历到的点,就可以看成是被裁掉的点,因为最终肯定会遇到割边达不到T,所以我们直接DFS残余网络的点数就可以得到最少的裁员人数了。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <queue>
     4 #include <algorithm>
     5 using namespace std;
     6 #define N 5010
     7 #define INF 0x3f3f3f3f
     8 typedef long long LL;
     9 struct Edge {
    10     int v, nxt, cap;
    11 } edge[100000];
    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 DFS(int u) {
    65     vis[u] = 1; int ans = 1;
    66     for(int i = head[u]; ~i; i = edge[i].nxt)
    67         if(edge[i].cap > 0 && !vis[edge[i].v]) ans += DFS(edge[i].v);
    68     return ans;
    69 }
    70 
    71 int main() {
    72     int n, m;
    73     while(~scanf("%d%d", &n, &m)) {
    74         S = 0, T = n + 1;
    75         LL sum = 0; int u, v; tot = 0;
    76         memset(head, -1, sizeof(head));
    77         memset(vis, 0, sizeof(vis));
    78         for(int i = 1; i <= n; i++) {
    79             int w; scanf("%d", &w);
    80             if(w > 0) Add(S, i, w), sum += w;
    81             else Add(i, T, -w);
    82         }
    83         for(int i = 1; i <= m; i++) {
    84             int u, v;
    85             scanf("%d%d", &u, &v);
    86             Add(u, v, INF);
    87         }
    88         LL ans = ISAP(T + 1);
    89         int res = DFS(S);
    90         printf("%d %lld
    ", --res, sum - ans);
    91     }
    92     return 0;
    93 }
  • 相关阅读:
    Linux 文件的软连接和硬连接
    URLOS发布NFS文件加速功能,可有效提升NFS小文件读取性能
    Vue底层学习3——手撸发布订阅模式
    Vue底层学习2——手撸数据响应化
    Vue底层学习1——原理解析
    rest api测试工具frisbyjs
    git ignore 微软临时文件(~$xxx.xlsx)
    数据虚拟化-基础概念
    elasticsearch移除映射类型(mapping type)
    activemq Virtual Destinations 虚拟目的地
  • 原文地址:https://www.cnblogs.com/fightfordream/p/6371021.html
Copyright © 2011-2022 走看看