LOJ 6001 太空飞行计划 (最大权闭合图+打印最小割)
来源:互联网 发布:知乎 原谅我红尘颠倒 编辑:程序博客网 时间:2024/06/08 05:51
题目描述
输入格式
输出格式
样例
数据范围与提示
题目大意:
有n个实验要做,做掉奖励相应的钱,但是每个实验需要相应的仪器,每个仪器启动起来要相应的钱,安排使得赚钱最多。
首先引入一个闭合图的概念。
闭合图就是原图的一个子图,如果一个点u在这个子图内,那么它连出去的所有点v也要在这个子图内。
最大权闭合图就是点的权值和最大的闭合图。
模型分析:
1.很明显这是一个二分图,每个实验向需要的仪器连有向边,实验的点权为正,仪器的点权为负,要求最大权闭合图。
2.这是一个选或不选的问题,所以可以转化成最小割的模型,把选的归为S集,不选的归为T集。但是要求获利最大,最小割是最小,所以我们要换个角度,要求扣的钱最少,因为所有实验的前都加起来是一定的。
3.在最小割中,如果把S到所有试验表示的点连一条容量为奖励的钱(A类弧),所有仪器到T连一条容量为启动仪器的钱(b类弧),如果把A类弧割掉了,那么对应的那个实验就归到了T集,也就是不做了,那么就会有损失。如果把B类弧割掉了,那么相应的那个仪器归到了S集,也就是有损失。所有最小割就是使得损失最少的方案。
构图方法:
1.增加源点S和汇点T。
2.从S到所有实验连一条边,容量为其获利,从所有仪器到T连一条边,容量为其花费。
3.从每个实验到相应的仪器连容量为inf的边.
用上述方法实际上只能过10/12的点,因为没有特判定,默认是做的实验越多越好.也就是说有多个最小割的时候,尽可能少割A类弧。所以我们可以把所有弧的容量都乘以一个较大的数,然后让A类弧的容量都+1。这样求出的最小割一定是原图的最小割,并且尽可能少割A类弧. 经过测试通过了所有测试点。
总结:
1.最大权闭合图的通用解法:S到正权值的点连边,容量为其权值,负权值的点到T连边,容量为其绝对值,然后原图中的边容量为inf,ans=所有正权和-最小割。具体证明可以参考胡伯涛的论文。
此题要求输出方案。Dinic 算法结束(残量网络中不存在
#include <iostream>#include <cstring>#include <algorithm>#include <cstdio>#include <queue>using namespace std;const int INF = 1e9;const int maxn = 105;const int maxv = 2e4;int head[maxv], cur[maxv], d[maxv], s, t, k, sum;int n, m;struct node{ int v, w, next;}edge[maxv+6*maxn];void addEdge(int u, int v, int w){ edge[k].v = v; edge[k].w = w; edge[k].next = head[u]; head[u] = k++; edge[k].v = u; edge[k].w = 0; edge[k].next = head[v]; head[v] = k++;}int bfs(){ memset(d, 0, sizeof(d)); d[s] = 1; queue<int> q; q.push(s); while(!q.empty()) { int u = q.front(); if(u == t) return 1; q.pop(); for(int i = head[u]; i != -1; i = edge[i].next) { int to = edge[i].v, w = edge[i].w; if(w && d[to] == 0) { d[to] = d[u] + 1; if(to == t) return 1; q.push(to); } } } return 0;}int dfs(int u, int maxflow){ if(u == t) return maxflow; int ret = 0; for(int i = cur[u]; i != -1; i = edge[i].next) { int to = edge[i].v, w = edge[i].w; if(w && d[to] == d[u]+1) { int f = dfs(to, min(maxflow-ret, w)); edge[i].w -= f; edge[i^1].w += f; ret += f; if(ret == maxflow) return ret; } } return ret;}int Dinic(){ int ans = 0; while(bfs() == 1) { memcpy(cur, head, sizeof(head)); ans += dfs(s, INF); } return ans;}char str[1000];int main(){ while(~scanf("%d%d", &m, &n)) { k = 0; s = 0; t = n+m+1; sum = 0; memset(head, -1, sizeof(head)); getchar(); for(int i = 1; i <= m; i++) { gets(str);// printf("%s\n", str) int len = strlen(str); int x = 0, j = 0; for(j = 0; j < len; j++) { if(str[j] == ' ') break; x = x*10 + str[j]-'0'; } addEdge(s, i, x); sum += x; x = 0; j++; for(; j < len; j++) { if(str[j] == ' ') { addEdge(i, x+m, INF); x = 0; continue; } if(j == len-1) { x = x*10 + str[j]-'0'; addEdge(i, x+m, INF); } x = x*10 + str[j]-'0'; } } for(int i = 1; i <= n; i++) { int x; scanf("%d", &x); addEdge(i+m, t, x); }// cout << Dinic() << endl;// cout << sum << endl; int ans = sum - Dinic();// for(int i = head[0]; i != -1; i = edge[i].next)// {// if(edge[i].w && !(i&1)) printf("%d ", edge[i].v);// } for(int i = 1; i <= m; i++) { if(d[i] != 0) printf("%d ", i); } puts("");// for(int i = m+1; i <= n+m; i++)// {// for(int j = head[i]; j != -1; j = edge[j].next)// {// if(!edge[j].w && !(j&1))// printf("%d ", i-m);// }// } for(int i = 1; i <= n; i++) { if(d[i+m] != 0) printf("%d ", i); } puts(""); printf("%d\n", ans); } return 0;}
- LOJ 6001 太空飞行计划 (最大权闭合图+打印最小割)
- 【网络流24题】太空飞行计划(最大权闭合图+最小割)
- loj6001「网络流 24 题」太空飞行计划(最大权闭合图+最小割)
- loj #6001. 「网络流 24 题」太空飞行计划(最大权闭合子图)
- 【网络流二十四题 太空飞行计划问题】【最大权闭合图->最小割】
- loj6001「网络流 24 题」太空飞行计划 最小割(最大权闭合图复习)
- 太空飞行计划 最大权闭合图
- 【loj】#6001. 「网络流 24 题」太空飞行计划(最大权闭合子图)
- LOJ 「网络流 24 题」太空飞行计划(最大权闭合子图)
- 太空飞行计划问题(最大权闭合图)
- 二、太空飞行计划问题 [最大权闭合图]
- Wiki 1233(太空飞行计划问题-最大权闭合子图)
- Wiki 1233(太空飞行计划问题-最大权闭合子图)
- ★ 太空飞行计划 最大权闭合图+输出方案
- pku2987 最小割,最大权闭合图
- 最小割---最大权闭合图简介
- 网络流-最大权闭合图(最小割求解)
- HDU 5855-最大权闭合图(-最小割应用)
- POJ 1321 棋盘问题
- [RK3288][Android6.0] 设置中通过Sensor旋转显示画面小结
- AngularJs Module init中使用sequelize创建数据库表
- 小技巧:虚线分割线
- 让人疑惑的Java代码
- LOJ 6001 太空飞行计划 (最大权闭合图+打印最小割)
- Qt中QThread线程与主线程的数据传送以及lineEdit的显示
- am命令基本知识
- ==和equals的区别
- TensorFlow实战:Chapter-5(CNN-3-经典卷积神经网络(GoogleNet))
- 执行Class.forName 报错 com.mysql.jdbc.Driverjava.lang.NullPointerException
- CPU下的计时与GPU计时对比
- 对nginx学习记录
- 交叉编译工具链的构建原理