POJ 2987 Firing

Firing

Time Limit: 5000ms

Memory Limit: 131072KB

This problem will be judged on PKU. Original ID: 2987
64-bit integer IO format: %lld      Java class name: Main

You’ve finally got mad at “the world’s most stupid” employees of yours and decided to do some firings. You’re now simply too mad to give response to questions like “Don’t you think it is an even more stupid decision to have signed them?”, yet calm enough to consider the potential profit and loss from firing a good portion of them. While getting rid of an employee will save your wage and bonus expenditure on him, termination of a contract before expiration costs you funds for compensation. If you fire an employee, you also fire all his underlings and the underlings of his underlings and those underlings’ underlings’ underlings… An employee may serve in several departments and his (direct or indirect) underlings in one department may be his boss in another department. Is your firing plan ready now?

Input

The input starts with two integers n (0 < n ≤ 5000) and m (0 ≤ m ≤ 60000) on the same line. Next follows n + m lines. The first n lines of these give the net profit/loss from firing the i-th employee individually bi (|bi| ≤ 107, 1 ≤ i ≤ n). The remaining m lines each contain two integers i and j (1 ≤ ij ≤ n) meaning the i-th employee has the j-th employee as his direct underling.

Output

Output two integers separated by a single space: the minimum number of employees to fire to achieve the maximum profit, and the maximum profit.

Sample Input

5 5
8
-9
-20
12
-10
1 2
2 5
1 4
3 4
4 5

Sample Output

2 2

Source

POJ Monthly--2006.08.27

解题:最大权闭合图

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cmath>
  5 #include <algorithm>
  6 #include <climits>
  7 #include <vector>
  8 #include <queue>
  9 #include <cstdlib>
 10 #include <string>
 11 #include <set>
 12 #include <stack>
 13 #define LL long long
 14 #define pii pair<int,int>
 15 #define INF 0x3f3f3f3f3f3f3f3fLL
 16 using namespace std;
 17 const int maxn = 5010;
 18 struct arc{
 19     int to,next;
 20     LL cap;
 21     arc(int x = 0,LL y = 0,int z = -1){
 22         to = x;
 23         cap = y;
 24         next = z;
 25     }
 26 };
 27 arc e[130010];
 28 int head[maxn],cur[maxn],d[maxn],q[maxn];
 29 int n,m,hd,tl,S,T,tot,cnt;
 30 bool vis[maxn];
 31 void add(int u,int v,int cap){
 32     e[tot] = arc(v,cap,head[u]);
 33     head[u] = tot++;
 34     e[tot] = arc(u,0,head[v]);
 35     head[v] = tot++;
 36 }
 37 bool bfs(){
 38     hd = tl = 0;
 39     memset(d,-1,sizeof(d));
 40     d[S] = 1;
 41     q[tl++] = S;
 42     while(hd < tl){
 43         int u = q[hd++];
 44         for(int i = head[u]; ~i; i = e[i].next){
 45             if(e[i].cap > 0 && d[e[i].to] == -1){
 46                 d[e[i].to] = d[u] + 1;
 47                 q[tl++] = e[i].to;
 48             }
 49         }
 50     }
 51     return d[T] > -1;
 52 }
 53 LL dfs(int u,LL low){
 54     if(u == T) return low;
 55     LL tmp = 0,a;
 56     for(int &i = cur[u]; ~i; i = e[i].next){
 57         if(e[i].cap > 0 && d[e[i].to] == d[u] + 1 && (a = dfs(e[i].to,min(low,e[i].cap)))){
 58             e[i].cap -= a;
 59             e[i^1].cap += a;
 60             tmp += a;
 61             low -= a;
 62             if(!low) break;
 63         }
 64     }
 65     if(!tmp) d[u] = -1;
 66     return tmp;
 67 }
 68 void go(int u){
 69     cnt++;
 70     vis[u] = true;
 71     for(int i = head[u]; ~i; i = e[i].next){
 72         if(e[i].cap > 0 && !vis[e[i].to]) go(e[i].to);
 73     }
 74 }
 75 int main(){
 76     LL ans,tmp;
 77     int u,v,w;
 78     while(~scanf("%d %d",&n,&m)){
 79         memset(head,-1,sizeof(head));
 80         memset(vis,false,sizeof(vis));
 81         S = ans = tot = cnt = 0;
 82         T = n + 1;
 83         for(int i = 1; i <= n; i++){
 84             scanf("%I64d",&tmp);
 85             if(tmp > 0){
 86                 ans += tmp;
 87                 add(S,i,tmp);
 88             }else if(tmp < 0) add(i,T,-tmp);
 89         }
 90         for(int i = 0; i < m; i++){
 91             scanf("%d %d",&u,&v);
 92             add(u,v,INF);
 93         }
 94         while(bfs()){
 95             memcpy(cur,head,sizeof(head));
 96             ans -= dfs(S,INF);
 97         }
 98         go(S);
 99         printf("%d %I64d\n",cnt-1,ans);
100     }
101     return 0;
102 }

时间: 2024-08-02 13:25:59

POJ 2987 Firing的相关文章

POJ 2987 Firing(最大权闭合)

POJ 2987 Firing 题目链接 题意:n个人,每个人被炒由于都会得到一个利益(可正可负),现在有一些下属关系,如果一个人被炒了,他的下属要一起炒掉,问怎么炒使得炒利益最大,炒的人最少 思路:最大权闭合的题,要处理最少,那么其实就是在求最小割分成两个集合的时候,尽量让点都到T集合去,那么只要从S进行一次dfs,遇到满流的边就停止,经过的点都给S,就是要炒掉的人了 代码: #include <cstdio> #include <cstring> #include <qu

POJ 2987 Firing (最大权闭合图,最小割)

http://poj.org/problem?id=2987 Firing Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 7865   Accepted: 2377 Description You've finally got mad at "the world's most stupid" employees of yours and decided to do some firings. You're n

poj - 2987 - Firing(最大权闭合图)

题意:n(0 < n ≤ 5000)个人,m(0 ≤ m ≤ 60000)个上下级关系,炒一个人可以获得收益或者损失bi (|bi| ≤ 10 ^ 7, 1 ≤ i ≤ n),炒一个人会把他的所有下级一起炒掉,问怎样炒人使收益最大,输出最大收益和最少炒人的数量. 题目链接:http://poj.org/problem?id=2987 -->>炒一个人会把他的所有下级一起炒掉,这时存在依赖关系,对应图论中的闭合图..最大收益对应最大权和..于是,最大权闭合图上场.. 最少炒人数?获得最大收

POJ 2987 Firing 最大权闭合图

点击打开链接 Firing Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 7976   Accepted: 2409 Description You've finally got mad at "the world's most stupid" employees of yours and decided to do some firings. You're now simply too mad to giv

POJ 2987 Firing 网络流 最大权闭合图

http://poj.org/problem?id=2987 https://blog.csdn.net/u014686462/article/details/48533253 给一个闭合图,要求输出其最大权闭合图的权值和需要选的最少点数,最大权闭合图定义和网络流连边方式见博客. 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cmath> 5 #include&

POJ 2987 Firing (最大权闭合图)

Firing Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 12108   Accepted: 3666 Description You've finally got mad at "the world's most stupid" employees of yours and decided to do some firings. You're now simply too mad to give resp

poj 2987 Firing【最大权闭合子图+玄学计数 || BFS】

玄学计数 LYY Orz 第一次见这种神奇的计数方式,乍一看非常不靠谱但是仔细想想还卡不掉 就是把在建图的时候把正权变成w*10000-1,负权变成w*10000+1,跑最大权闭合子图.后面的1作用是计数,因为在最大权闭合子图中划到s点一侧的代表选,这样一来,后四位就是起了计数作用.sum初始统计的个数就是所有正权点,然后dinic中割掉一个正权点的边即相当于在最终答案的后四位+1,也就是点数-1 然后考虑收益相同的方案,点数多的后四位一定小,而当前求得又是最小割,所以会选割掉点数少的,也就是留

POJ 2987 - Firing (最大权闭合子图)

题意:求一个图的最大权闭合子图 教科书:https://blog.csdn.net/can919/article/details/77603353 最小割模型的应用,源点向正权点建容量为该权值的弧;负权点向汇点建容量为该权值绝对值的弧;有偏序关系的点对之间建容量为正无穷的弧. 跑出最大流,根据最大流最小割定理:最大流的值即最小割.所求最大闭合子图的值为|正权点权值之和| - |最小割|. 此外,还要求删去人的数目.那么从源点出发,且不是最小割的边,就是被选择的边. 所以从源点dfs,若遇到容量不

poj 2987 最大权闭合图

Language: Default Firing Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 8744   Accepted: 2631 Description You’ve finally got mad at “the world’s most stupid” employees of yours and decided to do some firings. You’re now simply too mad