POJ 2987: Firing
来源:互联网 发布:中国国际形势印度知乎 编辑:程序博客网 时间:2024/06/07 04:06
题目链接:
http://poj.org/problem?id=2987题意:
现在有一群人,开除每个人都会有一个相应的收益(可正可负)。另给出他们之间的上下级关系,如果开除一个人就必须开除他的下属,以及他下属的下属,依次类推……
求最大收益的值以及在保证最大收益的前提下最少开除多少人。
算法:
有向图的最大权闭合子图——即闭合图内的任意点的任意后继也一定在闭合图中。
Amber的《最小割模型在信息学竞赛中的应用》里面已经讲解的非常清晰了。
从S到每一个点建一条边,权值为该点权值的绝对值。若该点权值为负,则由该点向T建边,权值为该点权值的绝对值。
若存在边(u, v),则由u 建一条到v 的边,流量为无限大。
最大收益为:正权值点的权值和 - 最小割
S割集为最大权闭合子图中的点,即应该被开除的人。代码:
#include <cstdio>#include <iostream>#include <algorithm>#include <sstream>#include <cstdlib>#include <cstring>#include <string>#include <climits>#include <cmath>#include <queue>#include <vector>#include <stack>#include <set>#include <map>#define INF 0x3f3f3f3fusing namespace std;const int maxn = 10000;const int maxm = 1000000;int to[maxm], nxt[maxm];long long cap[maxm];int head[maxn], cur[maxn], Q[maxn], dep[maxn];int E;void _addedge(int u, int v, long long w){ to[E] = v; cap[E] = w; nxt[E] = head[u]; head[u] = E ++;}void addedge(int u, int v, long long w){ _addedge(u, v, w); _addedge(v, u, 0);}bool bfs(int S, int T){ memset(dep, -1, sizeof(dep)); dep[T] = 0; int front = 0, rear = 0; Q[rear ++] = T; while (front != rear && dep[S] == -1) { int u = Q[front ++]; for (int i = head[u]; i != -1; i = nxt[i]) { int v = to[i]; if (cap[i ^ 1] && dep[v] == -1) { dep[v] = dep[u] + 1; Q[rear ++] = v; } } } return dep[S] != -1;}long long dfs(int S, int T, long long lim){ if (S == T) { return lim; } long long tmp = lim; for (int &i = cur[S]; i != -1; i = nxt[i]) { int v = to[i]; if (cap[i] && dep[S] == dep[v] + 1) { int ret = dfs(v, T, min(tmp, cap[i])); tmp -= ret; cap[i] -= ret; cap[i ^ 1] += ret; } if (!tmp) { break; } } return lim - tmp;}long long dinic(int S, int T, int n){ long long ans = 0; while (bfs(S, T)) { for (int i = 0; i < n; i ++) { cur[i] = head[i]; } ans += dfs(S, T, INT_MAX); } return ans;}void init(){ E = 0; memset(head, -1, sizeof(head));}int dfs(int u){ int cot = 1; for (int i = head[u]; i != -1; i = nxt[i]) { int v = to[i]; if (dep[v] == -1 && cap[i]) { dep[v] = dep[u] + 1; cot += dfs(v); } } return cot;}int main(){ int n, m; while (scanf("%d %d", &n, &m) == 2) { long long sum = 0; init(); int S = 0, T = n + 1; for (int i = 1; i <= n; i ++) { long long bonus; scanf("%lld", &bonus); if (bonus > 0) { addedge(S, i, bonus); sum += bonus; } else { addedge(i, T, -bonus); } } while (m --) { int u, v; scanf("%d %d", &u, &v); addedge(u, v, INF); } long long flow = dinic(S, T, n + 2); memset(dep, -1, sizeof(dep)); dep[0] = 0; printf("%d %lld\n", dfs(0) - 1, sum - flow); } return 0;}
0 0
- POJ 2987 Firing
- poj 2987(Firing)
- poj 2987 Firing
- poj 2987 Firing
- POJ 2987 Firing
- POJ-2987-Firing
- POJ 2987: Firing
- POJ 2987 Firing 已翻译
- poj 2987 Firing ------最大权闭合图
- poj 2987 Firing(最大权闭合图)
- POJ 2987 Firing (最大权闭合图)
- POJ 2987 Firing 最大权闭合图
- POJ 2987 Firing---dinic求最大流
- poj 2987 Firing 最大权闭合图
- POJ 2987 Firing 最大权闭合图
- POJ 2987 Firing(最大权闭合)
- POJ 2987 Firing(最大权闭合)
- poj 2987 Firing【最大闭合子图】
- (总结)Web性能压力测试工具之Siege详解
- SendKeys 语句
- 从一个点云中提取索引
- 光电耦合器简介以及作用
- PowerShell为什么强大
- POJ 2987: Firing
- 一学就会之ado.net(一)
- 21.4 实例:读取目录下指定类型的文件的内容
- Linux 命令行操作(二)文件操作
- 抛弃LCDS和FMS,在tomcat下开发Red5应用(第五篇)-客户端和服务器端方法调用的参数传递
- Android上常见度量单位【xdpi、hdpi、mdpi、ldpi】解读
- Redis 之 主从复制
- 如何解决Please ensure that adb is correctly located at......
- 【剑指offer学习】求和为定值的两个数