http://poj.org/problem?id=2987
Firing
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 individuallybi (|bi| ≤ 107, 1 ≤ i ≤ n). The remaining m lines each contain two integers i and j (1 ≤ i, j ≤ 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 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
|
网络流。。。好强大。。。orz。。。
题意:
你的公司要裁员,裁掉某个员工可能会获得收益或损失金钱,如果裁掉某个员工,他所有的下属(直接/间接)也要被裁掉,一个员工可能有多个上级和下属,求最大收益及其最少人数。
分析:
点为员工,上级到下级之间连一条有向边,我们最后要求一个图,这个图是封闭的,即没有出边,使得点的权值和(获得/损失)最大,即求最大权闭合图。
最大权闭合图可转化为网络流解,此处仅给出方法,具体证明请参见Amber大神的《最小割模型在信息学竞赛中的应用》。
方法:
1.原图中的有向边的容量设为无穷大;
2.增加源点,连向点权为正的点,容量为点权;
3.增加汇点,点权为负的点连向汇点,容量为点权的绝对值;
4.求解该图的最小割,最大权和为正点权和减最小割;
5.在残留网络中进行深度优先搜索,去掉源点,即为最大权闭合图。
#include<cstdio> #include<iostream> #include<cstdlib> #include<algorithm> #include<ctime> #include<cctype> #include<cmath> #include<string> #include<cstring> #include<stack> #include<queue> #include<list> #include<vector> #include<map> #include<set> #define sqr(x) ((x)*(x)) #define LL long long #define itn int #define INF 0x3f3f3f3f #define PI 3.1415926535897932384626 #define eps 1e-10 #define maxm 70007<<1 #define maxn 5007 using namespace std; const long long INFLL=0x3f3f3f3f3f3f3f3f; int fir[maxn]; int u[maxm],v[maxm],nex[maxm]; long long cap[maxm],flow[maxm]; int e_max; int iter[maxn],q[maxn],lv[maxn]; void add_edge(int _u,int _v,long long _w) { int e; e=e_max++; u[e]=_u;v[e]=_v;cap[e]=_w; nex[e]=fir[u[e]];fir[u[e]]=e; e=e_max++; u[e]=_v;v[e]=_u;cap[e]=0; nex[e]=fir[u[e]];fir[u[e]]=e; } void dinic_bfs(int s) { int f,r; memset(lv,-1,sizeof lv); q[f=r=0]=s; lv[s]=0; while(f<=r) { int x=q[f++]; for (int e=fir[x];~e;e=nex[e]) { if (cap[e]>flow[e] && lv[v[e]]<0) { lv[v[e]]=lv[u[e]]+1; q[++r]=v[e]; } } } } long long dinic_dfs(int _u,int t,long long _f) { if (_u==t) return _f; for (int &e=iter[_u];~e;e=nex[e]) { if (cap[e]>flow[e] && lv[_u]<lv[v[e]]) { long long _d=dinic_dfs(v[e],t,min(_f,cap[e]-flow[e])); if (_d>0) { flow[e]+=_d; flow[e^1]-=_d; return _d; } } } return 0; } long long max_flow(int s,int t) { memset(flow,0,sizeof flow); long long total_flow=0; for (;;) { dinic_bfs(s); if (lv[t]<0) return total_flow; memcpy(iter,fir,sizeof iter); long long _f; while ((_f=dinic_dfs(s,t,INF))>0) total_flow+=_f; } return total_flow; } int cnt=0; bool vis[maxn]; void dfs(int _u) { cnt++; vis[_u]=true; for (int e=fir[_u];~e;e=nex[e]) if (!vis[v[e]] && cap[e]>flow[e]) dfs(v[e]); } int main() { #ifndef ONLINE_JUDGE freopen("/home/fcbruce/文档/code/t","r",stdin); #endif // ONLINE_JUDGE int n,m,w; long long W=0; scanf("%d%d",&n,&m); int s=0,t=n+1; e_max=0; memset(fir,-1,sizeof fir); for (int i=1;i<=n;i++) { scanf("%d",&w); if (w>0) { W+=w; add_edge(s,i,w); } if (w<0) { add_edge(i,t,-w); } } int _u,_v; for (int i=0;i<m;i++) { scanf("%d%d",&_u,&_v); add_edge(_u,_v,INFLL); } long long max_profit=W-max_flow(s,t); memset(vis,0,sizeof vis); dfs(s); printf("%d %I64d\n",--cnt,max_profit); return 0; }
POJ 2987 Firing (最大权闭合图,最小割),布布扣,bubuko.com
原文地址:http://blog.csdn.net/u012965890/article/details/38439477