题目描述

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行是仪器编号;最后一行是净收益。

输入输出样例

输入样例#1: 复制

2 3
10 1 2
25 2 3
5 6 7
输出样例#1: 复制

1 2
1 2 3
17

说明

感谢@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 太空飞行计划问题 网络流的更多相关文章

  1. 网络流24题:P2762 太空飞行计划问题

    P2762 太空飞行计划问题 题目背景 题目描述 W 教授正在为国家航天中心计划一系列的太空飞行.每次太空飞行可进行一系列商业性实验而获取利润.现已确定了一个可供选择的实验集合E={E1,E2,…,E ...

  2. 洛谷 P2762 太空飞行计划问题 P3410 拍照【最大权闭合子图】题解+代码

    洛谷 P2762 太空飞行计划问题 P3410 拍照[最大权闭合子图]题解+代码 最大权闭合子图 定义: 如果对于一个点集合,其中任何一个点都不能到达此集合以外的点,这就叫做闭合子图.每个点都有一个权 ...

  3. Luogu 2762 太空飞行计划 / Libre 6001 「网络流 24 题」太空飞行计划 (网络流,最大流)

    Luogu 2762 太空飞行计划 / Libre 6001 「网络流 24 题」太空飞行计划 (网络流,最大流) Description W 教授正在为国家航天中心计划一系列的太空飞行.每次太空飞行 ...

  4. P2762 太空飞行计划问题(网络流24题之一)

    题目描述 W 教授正在为国家航天中心计划一系列的太空飞行.每次太空飞行可进行一系列商业性实验而获取利润.现已确定了一个可供选择的实验集合E={E1,E2,…,Em},和进行这些实验需要使用的全部仪器的 ...

  5. 【luogu P2762 太空飞行计划问题】 题解

    题目链接:https://www.luogu.org/problemnew/show/P2762 算是拍照那个题的加强下. 输入真的很毒瘤.(都这么说但好像我的过了?) #include <qu ...

  6. 洛谷 P4174 [NOI2006]最大获利 && 洛谷 P2762 太空飞行计划问题 (最大权闭合子图 && 最小割输出任意一组方案)

    https://www.luogu.org/problemnew/show/P4174 最大权闭合子图的模板 每个通讯站建一个点,点权为-Pi:每个用户建一个点,点权为Ci,分别向Ai和Bi对应的点连 ...

  7. 洛谷 - P2762 - 太空飞行计划问题 - 最小割

    https://www.luogu.org/problemnew/solution/P2762 最小割对应的点,在最后一次更新中dinic的bfs会把他的dep重置掉.所以可以根据这个性质复原最小割. ...

  8. P2762 太空飞行计划问题 最大权闭合子图

    link:https://www.luogu.org/problemnew/show/P2762 题意 承担实验赚钱,但是要花去对应仪器的费用,仪器可能共用.求最大的收益和对应的选择方案. 思路 这道 ...

  9. luogu P2762 太空飞行计划问题

    好像是最大权闭合图,也就是最大流最小割啦,找出最大流的路径输出,这题如何建模呢,一样的先设源点和汇点,源点向每个计划连capacity为赞助数的边,每个计划连相应装置capacity为无穷的边,每个装 ...

随机推荐

  1. IKAnalyzer修改支持lucene8.0

    源码已经上传GitHub. 如果直接使用jar:IKAnalyzer-5.0.2. 在这我只是在原有代码结构上做了微调,让代码支持lucene8.0.

  2. AJ学IOS 之微博项目实战(5)微博自定义搜索框searchBar

    AJ分享,必须精品 一:效果 用UITextField简单定义一个搜索框 二:调用: 调用的代码,很简单,直接init就可以,以后加功能自己添加就行了. - (void)viewDidLoad { [ ...

  3. pandas basic cheatsheet

    "胖的要死"是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的.Pandas 纳入了大量库和一些标准的数据模型,提供了高效地操作大型数据集所需的工具. 有多大?这篇 ...

  4. 今天我们来谈谈jquery,

    ---恢复内容开始--- 首先从jquery的两种写法开始: 1.$(document).ready(function(){}); 首先我们的jquery是用来操作DOM节点的,所以必须等到文档加载完 ...

  5. eclipse 集成git工具

    1.eclipse git插件下载 打开Eclipse,然后点击Help>Install New Software>Add name:git location:http://downloa ...

  6. jmeter 聚合报告参数解释

    label:每个请求的名称 样本:发送给服务器的请求数量 平均值:平均响应时间,默认情况下是单个 Request 的平均响应时间,当使用了 Transaction Controller 时,也可以以T ...

  7. 【题解】P1291 百事世界杯之旅 - 期望dp

    P1291 [SHOI2002]百事世界杯之旅 声明:本博客所有题解都参照了网络资料或其他博客,仅为博主想加深理解而写,如有疑问欢迎与博主讨论✧。٩(ˊᗜˋ)و✧*。 题目描述 "--在 \ ...

  8. python之elasticsearch查询

    下载所需模块 python安装好的情况下,通过pip install elasticsearch进行es模块的安装 安装完成后通过pip list命中查询 导入模块 from elasticsearc ...

  9. 负载均衡服务之HAProxy基础配置(二)

    前文我们聊了下haproxy的global配置段中的常用参数的说明以及使用,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/12763245.html:今天我们来 ...

  10. Mysql数据操作指令

    -----多数据插入-----只要写一次insert指令,但是可以直接插入多条记录insert into table values(),(),(); 主键冲突我们插入值的时候,主键中已经存在某个值,插 ...