您的位置:首页 > 其它

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

2017-01-16 09:04 369 查看
Firing

Time Limit: 5000MS Memory Limit: 131072K
Total Submissions: 10248 Accepted: 3110
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 ≤ i, j ≤ n) meaning thei-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

Hint

As of the situation described by the sample input, firing employees 4 and 5 will produce a net profit of 2, which is maximum.
Source

POJ Monthly--2006.08.27, frkstyc
[Submit]   [Go Back]   [Status]  
[Discuss]

题解:最大权闭合子图。
http://www.cnblogs.com/wuyiqi/archive/2012/03/12/2391960.html 这里有详细的介绍


对于最少点的问题有一个结论:

通过最大流求解最大权闭合子图的问题,求出来的闭合子图点数也是最少的。
http://blog.renren.com/share/175546306/2819449819 这里有详细的证明

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<queue>
#define N 300003
#define LL long long
using namespace std;
const LL inf=1e17;
int n,m,tot,s,t;
int point
,v
,next
,last
,mark
;
int deep
,num
,cur
;
LL val
,remain
;
void add(int x,int y,LL z)
{
tot++; next[tot]=point[x]; point[x]=tot; v[tot]=y; remain[tot]=z;
tot++; next[tot]=point[y]; point[y]=tot; v[tot]=x; remain[tot]=0;
//cout<<x<<" "<<y<<" "<<z<<endl;
}
LL addflow(int s,int t)
{
int now=t; LL ans=inf;
while (now!=s) {
ans=min(ans,remain[last[now]]);
now=v[last[now]^1];
}
now=t;
while (now!=s) {
remain[last[now]]-=ans;
remain[last[now]^1]+=ans;
now=v[last[now]^1];
}
return ans;
}
void bfs(int s,int t)
{
for (int i=s;i<=t;i++) deep[i]=t;
queue<int> p; p.push(t); deep[t]=0;
while (!p.empty()) {
int now=p.front(); p.pop();
for (int i=point[now];i!=-1;i=next[i])
if (deep[v[i]]==t&&remain[i^1])
deep[v[i]]=deep[now]+1,p.push(v[i]);
}
}
LL isap(int s,int t)
{
int now=s; LL ans=0;
bfs(s,t);
for (int i=s;i<=t;i++) num[deep[i]]++;
for (int i=s;i<=t;i++) cur[i]=point[i];
while (deep[s]<t) {
if (now==t) {
ans+=addflow(s,t);
now=s;
}
bool pd=false;
for (int i=cur[now];i!=-1;i=next[i])
if (deep[now]==deep[v[i]]+1&&remain[i]) {
last[v[i]]=i;
cur[now]=i;
pd=true;
now=v[i];
break;
}
if (!pd) {
int minn=t;
for (int i=point[now];i!=-1;i=next[i])
if (remain[i]) minn=min(minn,deep[v[i]]);
if (!--num[deep[now]]) break;
num[deep[now]=minn+1]++;
cur[now]=point[now];
if (now!=s) now=v[last[now]^1];
}
}
return ans;
}
void dfs(int x)
{
mark[x]=1;
for(int i=point[x];i!=-1;i=next[i])
if (remain[i]&&!mark[v[i]]) dfs(v[i]);
}
int main()
{
freopen("a.in","r",stdin);
freopen("my.out","w",stdout);
scanf("%d%d",&n,&m);
tot=-1; LL sum=0;
memset(point,-1,sizeof(point));
for (int i=1;i<=n;i++) scanf("%I64d",&val[i]);
for (int i=1;i<=m;i++) {
int x,y; scanf("%d%d",&x,&y);
add(x+1,y+1,inf);
}
s=1; t=n+2;
for (int i=1;i<=n;i++)
if (val[i]>0) add(s,i+1,val[i]),sum+=val[i];
else add(i+1,t,-val[i]);
LL flow=isap(s,t);
dfs(s);
int k=0;
for (int i=1;i<=n;i++) if (mark[i+1]) k++;
printf("%d %I64d\n",k,sum-flow);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: