http://poj.org/problem?id=2987

题意:有公司要裁员,每裁一个人可以得到收益(有正有负),而且如果裁掉的这个人有党羽的话,必须将这个人的所有党羽都裁除,问最少的裁员人数是多少和最大收益是多少。

思路:有依赖关系,最大权闭合图。我们要得到最大收益,那么就是尽量选择更多收益为正数的人,选择更少收益为负数的人,因此我们将收益为正数的人与源点连一条边,将收益为负数的人与汇点连一条边,这样得到的割集就是未选择的收益为正数的人+选择的收益为负数的人(也可以是损失的收益),很明显答案要使这个割集越小越好,那么就是求最小割。我们能够得到的最大收益是所有正数的和sum,我们再用sum-最小割(损失的收益)就可以得到最大收益了。

至于最少的裁员人数,我也挺迷糊的。看到别人的“将从S出发能到达的点看做firing的集合中的点,其他的能到T的点看作不被firing的集合中的点,那么在做完最大流之后自然就不会有firing集合中的点指向不被firing的集合中的点的边了,否则就会形成增广路。”这句话后,似乎我们只要在最终的残余网络中,只要能从S遍历到的点,就可以看成是被裁掉的点,因为最终肯定会遇到割边达不到T,所以我们直接DFS残余网络的点数就可以得到最少的裁员人数了。

 #include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
#define N 5010
#define INF 0x3f3f3f3f
typedef long long LL;
struct Edge {
int v, nxt, cap;
} edge[];
int head[N], cur[N], dis[N], pre[N], gap[N], vis[N], S, T, tot; void Add(int u, int v, int cap) {
edge[tot] = (Edge) {v, head[u], cap}; head[u] = tot++;
edge[tot] = (Edge) {u, head[v], }; head[v] = tot++;
} int BFS() {
memset(dis, INF, sizeof(dis));
memset(gap, , sizeof(gap));
queue<int> que; que.push(T);
dis[T] = ; gap[]++;
while(!que.empty()) {
int u = que.front(); que.pop();
for(int i = head[u]; ~i; i = edge[i].nxt) {
int v = edge[i].v;
if(dis[v] < INF) continue;
dis[v] = dis[u] + ;
gap[dis[v]]++;
que.push(v);
}
}
} LL ISAP(int n) {
BFS();
memcpy(cur, head, sizeof(cur));
int u = pre[S] = S, i, flow, index; LL ans = ;
while(dis[S] < n) {
if(u == T) {
flow = INF;
for(i = S; i != T; i = edge[cur[i]].v)
if(flow > edge[cur[i]].cap) flow = edge[cur[i]].cap, index = i;
for(i = S; i != T; i = edge[cur[i]].v)
edge[cur[i]].cap -= flow, edge[cur[i]^].cap += flow;
u = index; ans += flow;
}
for(i = cur[u]; ~i; i = edge[i].nxt) if(edge[i].cap > && dis[edge[i].v] + == dis[u]) break;
if(~i) {
cur[u] = i; pre[edge[i].v] = u; u = edge[i].v;
} else {
int md = n + ;
if(--gap[dis[u]] == ) break;
for(i = head[u]; ~i; i = edge[i].nxt)
if(edge[i].cap > && dis[edge[i].v] < md) md = dis[edge[i].v], cur[u] = i;
gap[dis[u] = md + ]++;
u = pre[u];
}
}
return ans;
} int DFS(int u) {
vis[u] = ; int ans = ;
for(int i = head[u]; ~i; i = edge[i].nxt)
if(edge[i].cap > && !vis[edge[i].v]) ans += DFS(edge[i].v);
return ans;
} int main() {
int n, m;
while(~scanf("%d%d", &n, &m)) {
S = , T = n + ;
LL sum = ; int u, v; tot = ;
memset(head, -, sizeof(head));
memset(vis, , sizeof(vis));
for(int i = ; i <= n; i++) {
int w; scanf("%d", &w);
if(w > ) Add(S, i, w), sum += w;
else Add(i, T, -w);
}
for(int i = ; i <= m; i++) {
int u, v;
scanf("%d%d", &u, &v);
Add(u, v, INF);
}
LL ans = ISAP(T + );
int res = DFS(S);
printf("%d %lld\n", --res, sum - ans);
}
return ;
}

POJ 2987:Firing(最大权闭合图)的更多相关文章

  1. poj 2987 Firing 最大权闭合图

    题目链接:http://poj.org/problem?id=2987 You’ve finally got mad at “the world’s most stupid” employees of ...

  2. POJ 2987 - Firing - [最大权闭合子图]

    题目链接:http://poj.org/problem?id=2987 Time Limit: 5000MS Memory Limit: 131072K Description You’ve fina ...

  3. POJ 2987 Firing | 最大权闭合团

    一个点带权的图,有一些指向关系,删掉一个点他指向的点也不能留下,问子图最大权值 题解: 这是最大权闭合团问题 闭合团:集合内所有点出边指向的点都在集合内 构图方法 1.S到权值为正的点,容量为权值 2 ...

  4. POJ2987 Firing 最大权闭合图

    详情请参考http://www.cnblogs.com/kane0526/archive/2013/04/05/3001557.html 值得注意的地方,割边会把图分成两部分,一部分和起点相连,另一部 ...

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

    http://poj.org/problem?id=2987 https://blog.csdn.net/u014686462/article/details/48533253 给一个闭合图,要求输出 ...

  6. POJ 2987 Firing(最大权闭合图)

    [题目链接] http://poj.org/problem?id=2987 [题目大意] 为了使得公司效率最高,因此需要进行裁员, 裁去不同的人员有不同的效率提升效果,当然也有可能是负的效果, 如果裁 ...

  7. POJ 2987 Firing(最大流最小割の最大权闭合图)

    Description You’ve finally got mad at “the world’s most stupid” employees of yours and decided to do ...

  8. POJ 2987 Firing【最大权闭合图-最小割】

    题意:给出一个有向图,选择一个点,则要选择它的可以到达的所有节点.选择每个点有各自的利益或损失.求最大化的利益,以及此时选择人数的最小值. 算法:构造源点s汇点t,从s到每个正数点建边,容量为利益.每 ...

  9. poj 2987(最大权闭合图+割边最少)

    题目链接:http://poj.org/problem?id=2987 思路:标准的最大权闭合图,构图:从源点s向每个正收益点连边,容量为收益:从每个负收益点向汇点t连边,容量为收益的相反数:对于i是 ...

随机推荐

  1. Hadoop MapReduce编程入门案例

    Hadoop入门例程简介 一个.有些指令 (1)Hadoop新与旧API差异 新API倾向于使用虚拟课堂(象类),而不是接口.由于这更easy扩展. 比如,能够无需改动类的实现而在虚类中加入一个方法( ...

  2. ASP .NET Model

    Model是全局变量,一个页面一个 前台 @ModelWebApplication1.Models.Movie; @{ ViewBag.Title = "ModelTest"; } ...

  3. ELINK编程器典型场景之远程镜像

    当不想直接提供Hex/Bin等二进制程序文件给用户时,通过生成远程镜像功能将程序文件加密后,再提供给用户自行脱机下载来达到远程更新的目的. 远程镜像生成的一般步骤为由客户端提供SN码,本地依据SN码加 ...

  4. php如何去掉二维数组中重复的元素

    $arr=array( "1"=>array("a","b "), "2"=>array("a&q ...

  5. 在WPF程序中将控件所呈现的内容保存成图像

    原文:在WPF程序中将控件所呈现的内容保存成图像 有的时候,我们需要将控件所呈现的内容保存成图像保存下来,例如:InkCanvas的手写墨迹,WebBrowser中的网页等.可能有人会说,这个不就是截 ...

  6. Win8 Metro(C#)数字图像处理--2.69中点滤波器

    原文:Win8 Metro(C#)数字图像处理--2.69中点滤波器 [函数代码] <strong> /// <summary> /// Mid-point filter. / ...

  7. HLS(HTTP Live Streaming)学习和探讨

    Introduction HTTP Live Streaming lets you send audio and video over HTTP from an ordinary web server ...

  8. WPF生成二维码

    WPF可以通过ZXing.Net库来实现二维码的功能. 可以通过NuGet安装: Install-Package ZXing.Net 二维码的实现代码: #region 二维码的方法 /// < ...

  9. C# WebRequest POST上传数据

    WebRequest request = WebRequest.Create("http://www.cnsos.net"); // Set the Method property ...

  10. Android零基础入门第31节:几乎不用但要了解的AbsoluteLayout绝对布局

    原文:Android零基础入门第31节:几乎不用但要了解的AbsoluteLayout绝对布局 前面几期基本学习了Android开发中常用的四种布局,之所以把AbsoluteLayout放在后面来学习 ...