POJ 2987 Firing (最大权闭合图)

Posted zgqblogs

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 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
思路:
有一张图够了,来自:
https://www.cnblogs.com/kane0526/archive/2013/04/05/3001557.html技术分享图片

值得一提的是,我在DFS找点数的过程中,在残余网络中寻找时,限制了k(边下标)为偶数,以表示该边是原图中的边。(因为我的网络流奇数边是原图的反向边),但是WA,去掉这个限制就对了,目前不知道问题出在哪里。

技术分享图片
  1 #include<iostream>
  2 #include<algorithm>
  3 #include<vector>
  4 #include<stack>
  5 #include<queue>
  6 #include<map>
  7 #include<set>
  8 #include<cstdio>
  9 #include<cstring>
 10 #include<cmath>
 11 #include<ctime>
 12 #define fuck(x) cout<<#x<<" = "<<x<<endl;
 13 #define ls (t<<1)
 14 #define rs ((t<<1)+1)
 15 using namespace std;
 16 typedef long long ll;
 17 typedef unsigned long long ull;
 18 const int maxn = 300086;
 19 const ll Inf = 999999999999999;
 20 const int mod = 1000000007;
 21 //const double eps = 1e-6;
 22 //const double pi = acos(-1);
 23 int n,m,s,t;
 24 int Head[5510],v[maxn],Next[maxn],cnt;
 25 ll w[maxn];
 26 void init(){
 27     s=0;t=n+2;
 28     memset(Head,-1,sizeof(Head));
 29     cnt=0;
 30 }
 31 int vis[5510],num[5510];
 32 void add(int x,int y,ll z)
 33 {
 34 //    cout<<x<<" "<<y<<" "<<z<<endl;
 35     if(x==y){return;}
 36     v[cnt]=y;
 37     w[cnt]=z;
 38     Next[cnt]=Head[x];
 39     Head[x]=cnt++;
 40 
 41     v[cnt]=x;
 42     w[cnt]=0;
 43     Next[cnt]=Head[y];
 44     Head[y]=cnt++;
 45 }
 46 
 47 bool bfs()
 48 {
 49     memset(vis,0,sizeof(vis));
 50     for(int i=0;i<=t;i++){
 51         num[i]=Head[i];
 52     }
 53     vis[s]=1;
 54     queue<int>q;
 55     q.push(s);
 56     int r=0;
 57     while(!q.empty()){
 58         int u=q.front();
 59         q.pop();
 60         int k=Head[u];
 61         while(k!=-1){
 62             if(!vis[v[k]]&&w[k]){
 63                 vis[v[k]]=vis[u]+1;
 64                 q.push(v[k]);
 65             }
 66             k=Next[k];
 67         }
 68     }
 69     return vis[t];
 70 }
 71 
 72 ll dfs(int u,ll f)
 73 {
 74 
 75     if(u==t){return f;}
 76     int &k=num[u];
 77     while(k!=-1){
 78         if(vis[v[k]]==vis[u]+1&&w[k]){
 79             ll d=dfs(v[k],min(f,w[k]));
 80             if(d>0){
 81                 w[k]-=d;
 82                 w[k^1]+=d;
 83 //                fuck(d)
 84                 return d;
 85             }
 86         }
 87         k=Next[k];
 88     }
 89     return 0ll;
 90 }
 91 ll Dinic()
 92 {
 93     ll ans=0;
 94     while(bfs()){
 95         ll f;
 96         while((f=dfs(s,Inf))>0){
 97             ans+=f;
 98         }
 99     }
100     return ans;
101 }
102 
103 int ans2=0;
104 
105 void dfst(int x)
106 {
107     ans2++;
108     vis[x]=1;
109     for(int k=Head[x];k!=-1;k=Next[k]){
110         if(w[k]&&!vis[v[k]]){dfst(v[k]);}
111     }
112 }
113 
114 int main()
115 {
116 //    ios::sync_with_stdio(false);
117 //    freopen("in.txt","r",stdin);
118 
119     scanf("%d%d",&n,&m);
120     init();
121     ll all=0;
122     for(int i=1;i<=n;i++){
123         ll x;
124         scanf("%lld",&x);
125         if(x>0){all+=x;add(s,i,x);}
126         else{
127             add(i,t,-x);
128         }
129     }
130     for(int i=1;i<=m;i++){
131         int x,y;
132         scanf("%d%d",&x,&y);
133         add(x,y,Inf);
134     }
135     ll ans1=all-Dinic();
136 
137     memset(vis,0,sizeof(vis));
138 
139     dfst(s);
140     printf("%d %lld
",ans2-1,ans1);
141     return 0;
142 }
View Code

 

 



以上是关于POJ 2987 Firing (最大权闭合图)的主要内容,如果未能解决你的问题,请参考以下文章

POJ 2987 Firing | 最大权闭合团

poj2987 Firing[最小割]

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

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

POJ 3155 最大密度子图

POJ2987:Firing——题解