P2762 太空飞行计划问题 网络流
题目描述
W 教授正在为国家航天中心计划一系列的太空飞行。每次太空飞行可进行一系列商业性实验而获取利润。现已确定了一个可供选择的实验集合E={E1,E2,…,Em},和进行这些实验需要使用的全部仪器的集合I={I1,I2,…In}。实验Ej需要用到的仪器是I的子集RjÍI。配置仪器Ik的费用为ck美元。实验Ej的赞助商已同意为该实验结果支付pj美元。W教授的任务是找出一个有效算法,确定在一次太空飞行中要进行哪些实验并因此而配置哪些仪器才能使太空飞行的净收益最大。这里净收益是指进行实验所获得的全部收入与配置仪器的全部费用的差额。
对于给定的实验和仪器配置情况,编程找出净收益最大的试验计划。
输入输出格式
输入格式:
第1行有2 个正整数m和n。m是实验数,n是仪器数。接下来的m 行,每行是一个实验的有关数据。第一个数赞助商同意支付该实验的费用;接着是该实验需要用到的若干仪器的编号。最后一行的n个数是配置每个仪器的费用。
输出格式:
第1 行是实验编号;第2行是仪器编号;最后一行是净收益。
输入输出样例
说明
感谢@FlierKing 提供spj
n,m<=50
这道题数据是在windows生成的,输入数据中所有的换行都是'\r\n'而不是'\n'
读入某实验需要用到的仪器编号的时候,可以这么读入。(感谢@zhouyonglong的提供)
char tools[];
memset(tools,,sizeof tools);
cin.getline(tools,);
int ulen=,tool;
while (sscanf(tools+ulen,"%d",&tool)==)//之前已经用scanf读完了赞助商同意支付该实验的费用
{//tool是该实验所需仪器的其中一个
//这一行,你可以将读进来的编号进行储存、处理,如连边。
if (tool==)
ulen++;
else {
while (tool) {
tool/=;
ulen++;
}
}
ulen++;
}
这个是一个网络流的最小割问题,对于最小割的学习,推荐一个博客:https://www.cnblogs.com/TreeDream/p/5942354.html
对于这个输出路径,可以看一下一段话,别人写的:
首先可以确定,最后一次分层之前,网络流里已经没有增广路径了,接着就退出while循环,这个很好理解。然后想想看为点分层的条件,一个是还没有分层,另一个就是边的容量大于0。再结合问题想想,如果我要做一个实验,那么我必须要盈利,如果我得不到利益,我肯定不会去做对吧。放到图里就是从源点流出一道流到对应的实验,然后这个流分别流向这个实验需要的仪器,在流到汇点时,仪器与汇点连接的边的容量之和,一定要小于源点到实验这条边的容量,也就是说我的花费要小于我的利益,才能有收益。那么对于容量大于0的边(从源点到实验对应的点),其实剩余的容量就是我做这个实验的收益了,这也可以解释总收益减去最大流(即总花费)是净收益。那些残量为0的边说明这个实验得不到收益,那就不选,在分层时就不会分配到值。好了,那么那些残量大于0的边所连的实验就是要做的实验了。至于仪器嘛,因为实验与仪器之间的边容量是inf,所以只要实验选了,分了层了,它需要的仪器自然也会分到层。
#include <cstdio>
#include <cstdlib>
#include <queue>
#include <vector>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>
#define inf 0x3f3f3f3f
using namespace std;
const int maxn = 1e5 + ;
struct node
{
int u, v, c, f;
node(int u=,int v=,int c=,int f=):u(u),v(v),c(c),f(f){}
};
vector<node>e;
vector<int>G[maxn];
int level[maxn], iter[maxn];
int m;
void init()
{
for (int i = ; i <= maxn; i++) G[i].clear();
e.clear();
}
void add(int u,int v,int c)
{
e.push_back(node(u, v, c, ));
e.push_back(node(v, u, , ));
m = e.size();
G[u].push_back(m - );
G[v].push_back(m - );
} void BFS(int s)
{
memset(level, -, sizeof(level));
queue<int>que;
que.push(s);
level[s] = ;
while(!que.empty())
{
int u = que.front(); que.pop();
for(int i=;i<G[u].size();i++)
{
node &now = e[G[u][i]];
if(level[now.v]<&&now.c>now.f)
{
level[now.v] = level[u] + ;
que.push(now.v);
}
}
}
} int dfs(int u,int v,int f)
{
if (u == v) return f;
for(int &i=iter[u];i<G[u].size();i++)
{
node &now = e[G[u][i]];
if(now.c>now.f&&level[now.v]==level[u]+)
{
int d = dfs(now.v, v, min(f, now.c - now.f));
if(d>)
{
now.f += d;
e[G[u][i] ^ ].f -= d;
return d;
}
}
}
return ;
} int dinic(int s,int t)
{
int flow = ;
while()
{
BFS(s);
if (level[t] < ) return flow;
memset(iter, , sizeof(iter));
int f = ;
while ((f = dfs(s, t, inf)) > ) flow += f;
}
return flow;
}
vector<int>vec[];
int a[];
int main()
{
int n, m, sum = ;
cin >> n >> m;
int s = , t = n + m + ;
for(int i=;i<=n;i++)
{
int x;
cin >> x;
add(s, i, x);
sum += x;
char tools[];
memset(tools, , sizeof tools);
cin.getline(tools, );
int ulen = , tool;
while (sscanf(tools + ulen, "%d", &tool) == )
{
add(i, tool+n, inf);
if (tool == ) ulen++;
else {
while (tool) {
tool /= ;
ulen++;
}
}
ulen++;
}
}
for (int i = ; i <= m; i++)
{
cin >> a[i];
add(i + n, t, a[i]);
}
int ans = dinic(s, t);
for (int i = ; i <= n; i++) if (level[i] >= ) printf("%d ", i);
printf("\n");
for (int i = ; i <= m; i++) if (level[i + n] >= ) printf("%d ",i);
printf("\n");
printf("%d\n", sum - ans);
return ;
} /*
首先可以确定,最后一次分层之前,网络流里已经没有增广路径了,接着就退出while循环,这个很好理解。
然后想想看为点分层的条件,一个是还没有分层,另一个就是边的容量大于0。再结合问题想想,如果我要做一个实验,
那么我必须要盈利,如果我得不到利益,我肯定不会去做对吧。放到图里就是从源点流出一道流到对应的实验,
然后这个流分别流向这个实验需要的仪器,在流到汇点时,仪器与汇点连接的边的容量之和,一定要小于源点到实验这条边的容量,
也就是说我的花费要小于我的利益,才能有收益。那么对于容量大于0的边(从源点到实验对应的点),
其实剩余的容量就是我做这个实验的收益了,这也可以解释总收益减去最大流(即总花费)是净收益。
那些残量为0的边说明这个实验得不到收益,那就不选,在分层时就不会分配到值。
好了,那么那些残量大于0的边所连的实验就是要做的实验了。至于仪器嘛,因为实验与仪器之间的边容量是inf,
所以只要实验选了,分了层了,它需要的仪器自然也会分到层。
*/
P2762 太空飞行计划问题 网络流的更多相关文章
- 网络流24题:P2762 太空飞行计划问题
P2762 太空飞行计划问题 题目背景 题目描述 W 教授正在为国家航天中心计划一系列的太空飞行.每次太空飞行可进行一系列商业性实验而获取利润.现已确定了一个可供选择的实验集合E={E1,E2,…,E ...
- 洛谷 P2762 太空飞行计划问题 P3410 拍照【最大权闭合子图】题解+代码
洛谷 P2762 太空飞行计划问题 P3410 拍照[最大权闭合子图]题解+代码 最大权闭合子图 定义: 如果对于一个点集合,其中任何一个点都不能到达此集合以外的点,这就叫做闭合子图.每个点都有一个权 ...
- Luogu 2762 太空飞行计划 / Libre 6001 「网络流 24 题」太空飞行计划 (网络流,最大流)
Luogu 2762 太空飞行计划 / Libre 6001 「网络流 24 题」太空飞行计划 (网络流,最大流) Description W 教授正在为国家航天中心计划一系列的太空飞行.每次太空飞行 ...
- P2762 太空飞行计划问题(网络流24题之一)
题目描述 W 教授正在为国家航天中心计划一系列的太空飞行.每次太空飞行可进行一系列商业性实验而获取利润.现已确定了一个可供选择的实验集合E={E1,E2,…,Em},和进行这些实验需要使用的全部仪器的 ...
- 【luogu P2762 太空飞行计划问题】 题解
题目链接:https://www.luogu.org/problemnew/show/P2762 算是拍照那个题的加强下. 输入真的很毒瘤.(都这么说但好像我的过了?) #include <qu ...
- 洛谷 P4174 [NOI2006]最大获利 && 洛谷 P2762 太空飞行计划问题 (最大权闭合子图 && 最小割输出任意一组方案)
https://www.luogu.org/problemnew/show/P4174 最大权闭合子图的模板 每个通讯站建一个点,点权为-Pi:每个用户建一个点,点权为Ci,分别向Ai和Bi对应的点连 ...
- 洛谷 - P2762 - 太空飞行计划问题 - 最小割
https://www.luogu.org/problemnew/solution/P2762 最小割对应的点,在最后一次更新中dinic的bfs会把他的dep重置掉.所以可以根据这个性质复原最小割. ...
- P2762 太空飞行计划问题 最大权闭合子图
link:https://www.luogu.org/problemnew/show/P2762 题意 承担实验赚钱,但是要花去对应仪器的费用,仪器可能共用.求最大的收益和对应的选择方案. 思路 这道 ...
- luogu P2762 太空飞行计划问题
好像是最大权闭合图,也就是最大流最小割啦,找出最大流的路径输出,这题如何建模呢,一样的先设源点和汇点,源点向每个计划连capacity为赞助数的边,每个计划连相应装置capacity为无穷的边,每个装 ...
随机推荐
- C#多线程(4):进程同步Mutex类
Mutex 类 构造函数和方法 系统只能运行一个程序的实例 解释一下上面的示例 接替运行 进程同步示例 另外 Mutex 类 Mutex 中文为互斥,Mutex 类叫做互斥锁.它还可用于进程间同步的同 ...
- 【Java】 Variable 变量
什么是Variable变量? - 变量是内存中的一个存储区域 - 这个存储区域内的数据允许在同一类型范围内不断变化 - 是程序最基本的存储单元,包含三个要素[变量类型][变量名][存储的值] 为什么需 ...
- 理解SVG的缩放 偏移的计算公式
SVG中DOM元素的偏移与缩放都是基于SVG元素的左上角,所以如何理解与计算SVG中元素的真实位置就比较难,下面的例子都以圆(circle)为例. 1.缩放假定缩放的比例为s,执行缩放后,圆的圆心坐标 ...
- Three.js实现3D地图实例分享
本文主要给大家介绍了关于利用Three.js开发实现3D地图的实践过程,文中通过示例代码介绍的非常详细,对大家学习或者使用three.js具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习 ...
- 小说光看还不够?用Python做有声小说!
文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. PS:如有需要Python学习资料的小伙伴可以加点击下方链接自行获取http:// ...
- OkHttp 优雅封装 OkHttps 之 回调线程魔变
第一篇:OkHttp 优雅封装 HttpUtils 之 气海雪山初探 第二篇:OkHttp 优雅封装 HttpUtils 之 上传下载解密 简介 HttpUtils 从 v2.3.0 之后便重命名了, ...
- Linux学习笔记(四)帮助命令
帮助命令 man info help --help man 英文原意:format and display the on-line manual pages 功能:显示联机帮助手册 语法:man 选项 ...
- Epicor RoHS Overview
Epicor ERP具有一个旨在帮助符合指令2002/95/EC (RoHS1) and 2011/65/EU (RoHS2)的模块,特别适用于医疗设备公司. 不合格的依据是–最大浓度值和合格声明/ ...
- 【山外笔记-SVN命令】svnlook命令详解
本文打印版问文件下载地址 [山外笔记-SVN命令]svnlook命令详解-打印版.pdf 一.命令简介 svnlook是检验Subversion版本库不同方面的命令行工具,不会对版本库有任何修改,只是 ...
- Spring5:概念
1.Spring优点 spring是一个开源的免费的框架 spring是一个轻量级的 非入侵式的框架 控制反转(IOC).面向切面(AOP) 支持事务的处理,对框架整合的支持 **总之:spring就 ...