Firing (poj 2987 最大权闭合图)
2015-09-07 20:24
357 查看
Language: Default Firing
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 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 |
思路:最大权闭合图,关键是求最少的辞退人数,这里就为最小割的取点数,具体证明看这位大神吧点击打开链接
另外注意要用long long
代码:
#include <iostream> #include <functional> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <string> #include <map> #include <stack> #include <vector> #include <set> #include <queue> #pragma comment (linker,"/STACK:102400000,102400000") #define pi acos(-1.0) #define eps 1e-6 #define lson rt<<1,l,mid #define rson rt<<1|1,mid+1,r #define FRE(i,a,b) for(i = a; i <= b; i++) #define FREE(i,a,b) for(i = a; i >= b; i--) #define FRL(i,a,b) for(i = a; i < b; i++) #define FRLL(i,a,b) for(i = a; i > b; i--) #define mem(t, v) memset ((t) , v, sizeof(t)) #define sf(n) scanf("%d", &n) #define sff(a,b) scanf("%d %d", &a, &b) #define sfff(a,b,c) scanf("%d %d %d", &a, &b, &c) #define pf printf #define DBG pf("Hi\n") typedef long long ll; using namespace std; #define INF 1<<30 #define mod 1000000009 const int maxn = 5005; const int MAXN = 5005; const int MAXM = 200010; struct Edge { int to,next; ll cap,flow; }edge[MAXM]; int n,m; ll sum; int tol; int head[MAXN]; int gap[MAXN],dep[MAXN],pre[MAXN],cur[MAXN]; void init() { tol=0; memset(head,-1,sizeof(head)); } //加边,单向图三个参数,双向图四个参数 void addedge(int u,int v,ll w,ll rw=0) { edge[tol].to=v; edge[tol].cap=w; edge[tol].next=head[u]; edge[tol].flow=0; head[u]=tol++; edge[tol].to=u; edge[tol].cap=rw; edge[tol].next=head[v]; edge[tol].flow=0; head[v]=tol++; } //输入参数:起点,终点,点的总数 //点的编号没有影响,只要输入点的总数 ll sap(int start,int end,int N) { memset(gap,0,sizeof(gap)); memset(dep,0,sizeof(dep)); memcpy(cur,head,sizeof(head)); int u=start; pre[u]=-1; gap[0]=N; ll ans=0; while (dep[start]<N) { if (u==end) { ll Min=INF; for (int i=pre[u];i!=-1;i=pre[edge[i^1].to]) if (Min>edge[i].cap-edge[i].flow) Min=edge[i].cap-edge[i].flow; for (int i=pre[u];i!=-1;i=pre[edge[i^1].to]) { edge[i].flow+=Min; edge[i^1].flow-=Min; } u=start; ans+=Min; continue; } bool flag=false; int v; for (int i=cur[u];i!=-1;i=edge[i].next) { v=edge[i].to; if (edge[i].cap-edge[i].flow && dep[v]+1==dep[u]) { flag=true; cur[u]=pre[v]=i; break; } } if (flag) { u=v; continue; } ll Min=N; for (int i=head[u];i!=-1;i=edge[i].next) if (edge[i].cap-edge[i].flow && dep[edge[i].to]<Min) { Min=dep[edge[i].to]; cur[u]=i; } gap[dep[u]]--; if (!gap[dep[u]]) return ans; dep[u]=Min+1; gap[dep[u]]++; if (u!=start) u=edge[pre[u]^1].to; } return ans; } bool vis[maxn]; int cnt; void dfs(int u) { vis[u]=true; for (int i=head[u];~i;i=edge[i].next) { int v=edge[i].to; if (!vis[v]&&edge[i].cap-edge[i].flow>0) { cnt++; dfs(v); } } } int main() { #ifndef ONLINE_JUDGE freopen("C:/Users/lyf/Desktop/IN.txt","r",stdin); #endif int i,j,u,v; ll x; while (~scanf("%d%d",&n,&m)) { init(); sum=0; int S=0,T=n+1; for (i=1;i<=n;i++) { scanf("%lld",&x); if (x>0) { addedge(S,i,x); sum+=x; } else { addedge(i,T,-x); } } for (i=1;i<=m;i++) { scanf("%d%d",&u,&v); addedge(u,v,INF); } ll ans=sap(S,T,T+1); memset(vis,false,sizeof(vis)); cnt=0; dfs(S); printf("%d %lld\n",cnt,sum-ans); } return 0; }
相关文章推荐
- poj 1028 Web Navigation(模拟)
- C++ 之 explicit,mutable,volatile 浅析
- 键盘输入聊天
- java cpu占用过高分析
- 自我来扒一扒产品十宗罪
- 三子棋
- hdu 2011 多项式求和
- dom4j解析
- Mac 配置 Apache .php
- Android 自动适应字体大小的EditText
- UDP
- The Doors - POJ 1556 (线段相交)
- Vim 使用总结
- 在NeoKylin下安装QT5
- JSon
- SQL示例
- Codeforces Beta Round #96 (Div. 1) D. Constants in the language of Shakespeare 贪心
- 基础排序java实现
- 感动
- Day-1:C语言基本知识: