HDU 4971 A simple brute force problem.(最大权闭合)
来源:互联网 发布:伪装者于曼丽知乎 编辑:程序博客网 时间:2024/05/16 12:47
题目大意:有N个工程,完成一个工程获利pi. M个技术问题,解决一个技术问题需要花费ci
现在给出每个工程需要解决的技术问题,和解决一个技术问题前还需要解决哪些技术问题
问最大获利是多少
解题思路:最大权闭合的题目,构图的话
正权的话肯定是完成一个工程的获利,负权的话就是解决每个问题的费用了
接着是连边,可以画出图,他所需要的前置条件其实就是它所指向的点,这样就可以得到一张有向图了,有了有向图了,就可以建图了
具体的理论详见胡伯涛:算法合集之《最小割模型在信息学竞赛中的应用》
#include <cstdio>#include <cstring>#include <algorithm>#include <vector>#include <queue>using namespace std;const int MAXNODE = 210;const int MAXEDGE = 100010;typedef int Type;const Type INF = 0x3f3f3f3f;struct Edge { int u, v, next; Type cap, flow; Edge() {} Edge(int u, int v, Type cap, Type flow, int next): u(u), v(v), cap(cap), flow(flow), next(next) {}};struct ISAP { int n, m, s, t; Edge edges[MAXEDGE]; int head[MAXNODE], p[MAXNODE], num[MAXNODE], cur[MAXNODE], d[MAXNODE]; bool vis[MAXNODE]; void init(int n) { this->n = n; memset(head, -1, sizeof(head)); m = 0; } void AddEdge(int u, int v, Type cap) { edges[m] = Edge(u, v, cap, 0, head[u]); head[u] = m++; edges[m] = Edge(v, u, 0, 0, head[v]); head[v] = m++; } bool BFS() { memset(vis, 0, sizeof(vis)); queue<int> Q; for (int i = 0; i < n; i++) d[i] = INF; d[t] = 0; vis[t] = 1; Q.push(t); while (!Q.empty()) { int u = Q.front(); Q.pop(); for (int i = head[u]; ~i; i = edges[i].next) { Edge &e = edges[i ^ 1]; if (!vis[e.u] && e.cap > e.flow) { vis[e.u] = true; d[e.u] = d[u] + 1; Q.push(e.u); } } } return vis[s]; } Type Augment() { int u = t; Type flow = INF; while (u != s) { Edge &e = edges[p[u]]; flow = min(flow, e.cap - e.flow); u = edges[p[u]].u; } u = t; while (u != s) { edges[p[u]].flow += flow; edges[p[u] ^ 1].flow -= flow; u = edges[p[u]].u; } return flow; } Type Maxflow(int s, int t) { this->s = s; this->t = t; Type flow = 0; BFS(); //如果s-->t走不通 if (d[s] >= n) return 0; memset(num, 0, sizeof(num)); for (int i = 0; i < n; i++) cur[i] = head[i]; for (int i = 0; i < n; i++) if (d[i] < INF) num[d[i]]++; int u = s; while (d[s] < n) { if (u == t) { flow += Augment(); u = s; } bool ok = false;//纪录是否找到了下一个点 for (int i = cur[u]; ~i; i = edges[i].next) { Edge &e = edges[i]; if (e.cap > e.flow && d[u] == d[e.v] + 1) { ok = true; p[e.v] = i;//点v由第i条边增广得到 cur[u] = i;//尝试到第i条边 u = e.v; break; } } //如果没找到下一个点,表示u到t的最短路要变长了,或者没路可走了 if (!ok) { //找寻u到下一个点的最短路 int Min = n - 1; for (int i = head[u]; ~i; i = edges[i].next) { Edge &e = edges[i]; if (e.cap > e.flow) Min = min(Min, d[e.v]); } if (--num[d[u]] == 0)//GAP优化 break; num[d[u] = Min + 1]++; cur[u] = head[u]; //返回前一个点,因为该点的最短距离已经变了 if (u != s) u = edges[p[u]].u; } } return flow; }}isap;int n, m, source, sink;int Sum, cas = 1;void init() { scanf("%d%d", &n, &m); source = 0, sink = n + m + 1; isap.init(sink + 1); Sum = 0; int c, k; for (int i = 1; i <= n; i++) { scanf("%d", &c); isap.AddEdge(source, i, c); Sum += c; } for (int j = 1; j <= m; j++) { scanf("%d", &c); isap.AddEdge(j + n, sink, c); } for (int i = 1; i <= n; i++) { scanf("%d", &k); for (int j = 1; j <= k; j++) { scanf("%d", &c); isap.AddEdge(i, n + c + 1, INF); } } for (int i = 1; i <= m; i++) { for (int j = 1; j <= m; j++) { scanf("%d", &c); if (c) isap.AddEdge(n + i, n + j, INF); } } int maxflow = isap.Maxflow(source, sink); printf("Case #%d: %d\n", cas++, Sum - maxflow);}int main() { int test; scanf("%d", &test); while (test--) { init(); } return 0;}
0 0
- HDU 4971 A simple brute force problem.(最大权闭合)
- HDU 4971 A simple brute force problem. 强连通缩点+最大权闭合图
- 【HDU】4971 A simple brute force problem. 强连通缩点+最大权闭合子图
- HDU 4971 A simple brute force problem. 最大权闭合图
- HDU 4971 A simple brute force problem.(最小割,最大权闭合图)
- hdu 多校联合 4971 A simple brute force problem.(最大权闭合图)
- HDU 4971 A simple brute force problem 最大权闭合图
- HDU 4971 A simple brute force problem.(最小割---最大权闭合)
- hdu - 4971 - A simple brute force problem.(最大权闭合图)
- HDU 4971 A simple brute force problem.最大权闭合图
- HDU 4971 A simple brute force problem. 最小割 最大权闭合
- HDU 4971 A simple brute force problem.(最小割,最大权闭合图)
- hdu4917 A simple brute force problem.(最大权闭合)
- hdoj 4971 A simple brute force problem. 【最大权闭合图 --> 最小割】
- HDU_4971_A simple brute force problem.(最大权闭合图)
- hdu4971A simple brute force problem.【最大权闭合图】
- HDU-4971-A simple brute force problem.
- HDU 4971 A simple brute force problem.
- 交换、路由与防火墙手记(2)
- 文章标题
- 图解JavaScript
- 线程池
- 伸展树 - hdu1890 Robotic Sort
- HDU 4971 A simple brute force problem.(最大权闭合)
- 实现ArcGIS水文分析计算汇流累积量功能
- [转]在Ubuntu中安装Python科学计算环境
- 运用Polygon类绘制六边形
- 蓝汛ChinaCache助力大阅兵全球直播
- 数组和指针的区别
- HTTP 状态码的完整列表
- AJAX学习笔记
- newssoj1004逐个击破attack(排序+并查集)