hdoj 3996 Gold Mine 【最小割 之 最大权闭合图】
来源:互联网 发布:读取二维码扫码枪数据 编辑:程序博客网 时间:2024/05/21 15:51
Gold Mine
Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2415 Accepted Submission(s): 525
Problem Description
Long long ago, there is a gold mine.The mine consist of many layout, so some area is easy to dig, but some is very hard to dig.To dig one gold, we should cost some value and then gain some value. There are many area that have gold, because of the layout, if one people want to dig one gold in some layout, he must dig some gold on some layout that above this gold's layout. A gold seeker come here to dig gold.The question is how much value the gold he can dig, suppose he have infinite money in the begin.
Input
First line the case number.(<=10)
Then for every case:
one line for layout number.(<=100)
for every layout
first line gold number(<=25)
then one line for the dig cost and the gold value(32bit integer), the related gold number that must be digged first(<=50)
then w lines descripte the related gold followed, each line two number, one layout num, one for the order in that layout
see sample for details
Then for every case:
one line for layout number.(<=100)
for every layout
first line gold number(<=25)
then one line for the dig cost and the gold value(32bit integer), the related gold number that must be digged first(<=50)
then w lines descripte the related gold followed, each line two number, one layout num, one for the order in that layout
see sample for details
Output
Case #x: y.
x for case number, count from 1.
y for the answer.
x for case number, count from 1.
y for the answer.
Sample Input
12110 100 0210 100 11 110 100 11 1
Sample Output
Case #1: 270
题意:有一座矿山,矿山里面有N个待开发的地方,每个地方都会有一定数目的金矿,开采一个金矿会花费一定数目的金币,相应的也会有一定的收益。但是对于每个金矿,在开采它之前,必须要先开采与它有联系的所有金矿。假设初始拥有的费用是无穷大的,现在问你能获得的最大收益。
思路:明显的最大权闭合图,找出依赖关系,建好图,直接就是最小割了。
建图:设置超级源点source,超级汇点sink
1,source向所有正收益的金矿建边,容量为正收益;
2,所有负收益的金矿向sink建边,容量为负收益;
3,依赖关系a -> b(必须先开采b再开采a)建边,容量为无穷大。
记录所有正收益之和sum,答案就是sum - 最小割。
注意:会超int型,还有无穷大的值要设大点。
AC代码:最后结果题目给出的数据,不会有负数,所以直接输出答案也是可以的。
#include <cstdio>#include <cstring>#include <queue>#include <algorithm>#define MAXN 3000#define MAXM 500000#define INF 0x3f3f3f3f3f#define LL long longusing namespace std;struct Edge{ int from, to; LL cap, flow;; int next;};Edge edge[MAXM];int head[MAXN], edgenum;int dist[MAXN], cur[MAXN];bool vis[MAXN];int N;void init(){ edgenum = 0; memset(head, -1, sizeof(head));}void addEdge(int u, int v, LL w){ Edge E1 = {u, v, w, 0, head[u]}; edge[edgenum] = E1; head[u] = edgenum++; Edge E2 = {v, u, 0, 0, head[v]}; edge[edgenum] = E2; head[v] = edgenum++;}LL sum;//记录图中所有正权点 的权值之和int source, sink;struct Node{ LL c, g; int w, layout[60], order[60];};Node rec[110][30];//记录第i个layout的第j个gold的信息int num[110];//记录第i个layout里面有多少个goldint have[110];//记录第i个layout前面有多少个goldvoid getMap(){ sum = 0; int t = 0; for(int i = 1; i <= N; i++) { have[i] = t; scanf("%d", &num[i]); t += num[i]; for(int j = 1; j <= num[i]; j++) { scanf("%lld%lld%d", &rec[i][j].c, &rec[i][j].g, &rec[i][j].w); for(int k = 0; k < rec[i][j].w; k++) scanf("%d%d", &rec[i][j].layout[k], &rec[i][j].order[k]); } } source = 0, sink = t+1; for(int i = 1; i <= N; i++) { for(int j = 1; j <= num[i]; j++) { int u = have[i] + j; if(rec[i][j].g - rec[i][j].c > 0) addEdge(source, u, rec[i][j].g - rec[i][j].c), sum += rec[i][j].g - rec[i][j].c; else addEdge(u, sink, -rec[i][j].g + rec[i][j].c); for(int k = 0; k < rec[i][j].w; k++)//依赖关系建边 { int v = have[rec[i][j].layout[k]] + rec[i][j].order[k]; addEdge(u, v, INF); } } }}bool BFS(int s, int t){ queue<int> Q; memset(dist, -1, sizeof(dist)); memset(vis, false, sizeof(vis)); dist[s] = 0; vis[s] = true; Q.push(s); while(!Q.empty()) { int u = Q.front(); Q.pop(); for(int i = head[u]; i != -1; i = edge[i].next) { Edge E = edge[i]; if(!vis[E.to] && E.cap > E.flow) { dist[E.to] = dist[u] + 1; if(E.to == t) return true; vis[E.to] = true; Q.push(E.to); } } } return false;}LL DFS(int x, LL a, int t){ if(x == t || a == 0) return a; LL flow = 0, f; for(int &i = cur[x]; i != -1; i = edge[i].next) { Edge &E = edge[i]; if(dist[E.to] == dist[x] + 1 && (f = DFS(E.to, min(a, E.cap-E.flow), t)) > 0) { edge[i].flow += f; edge[i^1].flow -= f; flow += f; a -= f; if(a == 0) break; } } return flow;}LL Maxflow(int s, int t){ LL flow = 0; while(BFS(s, t)) { memcpy(cur, head, sizeof(head)); flow += DFS(s, INF, t); } return flow;}int main(){ int t, k = 1; scanf("%d", &t); while(t--) { scanf("%d", &N); init(); getMap(); LL ans = sum - Maxflow(source, sink); printf("Case #%d: %lld\n", k++, ans > 0 ? ans : 0); } return 0;}
0 0
- hdoj 3996 Gold Mine 【最小割 之 最大权闭合图】
- HDU 3996 Gold Mine(最小割---最大权闭合)
- hdu 3996 Gold Mine (最大权闭合图)
- 【HDU】3996 Gold Mine 最大权闭合子图
- HDU 3996 Gold Mine 最大权闭合图
- HDU 3996 Gold Mine 最大权闭合图
- HDU 3996 Gold Mine(最大权闭合图)
- hdoj 3879 Base Station 【最小割 之 最大权闭合图】
- hdoj 3917 Road constructions 【最小割 之 最大权闭合图】
- hdoj 3061 Battle 【最小割 之 最大权闭合图】 【入门题目】
- hdu 3996 Gold Mine【最大权闭包-----最小割最大流Dinic】
- pku2987 最小割,最大权闭合图
- 最小割---最大权闭合图简介
- HDOJ 3879 - Base Station 最大权闭合子图(最小割解决)
- hdoj 4971 A simple brute force problem. 【最大权闭合图 --> 最小割】
- 多校第16场 HDU3996 Gold Mine (最大权闭合图)
- HDU3996 Gold Mine最大权闭合图 2011 Multi-University Training Contest 16 - Host by TJU
- POJ 2987 最大流最小割最大权闭合图
- Leetcode: Sqrt(x)
- Java中for与foreach区别
- jstl的formatNumber标签的四舍五入问题
- Android 网络操作(其中包含xUtils的HttpUtils联网)
- js获得浏览器页面上某一个参数
- hdoj 3996 Gold Mine 【最小割 之 最大权闭合图】
- 数组指针和指针数组的区别
- Ubuntu入门(1): 获取 root 权限
- java中的分页(最基础的方法)
- 看完《形式感+网页视觉设计创意拓展与快速表现》总结
- 爸爸去哪儿第三季之<刘诺一>8.28第八期
- resteasy拦截器,拦截rest请求,修改response header内容
- window7配置Qt
- 判断二叉树是否为子树