题目描述

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. 运用JAVA的concurrent.ExecutorService线程池实现socket的TCP和UDP连接

    运用JAVA的concurrent.ExecutorService线程池实现socket的TCP和UDP连接 最近在项目中可能要用到socket相关的东西来发送消息,所以初步研究了下socket的TC ...

  2. 【python实现卷积神经网络】padding2D层实现

    代码来源:https://github.com/eriklindernoren/ML-From-Scratch 卷积神经网络中卷积层Conv2D(带stride.padding)的具体实现:https ...

  3. 解决Jquery中click里面包含click事件,出现重复执行的问题

    出现问题的代码: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.o ...

  4. PDM添加唯一性约束

  5. Android | 教你如何在安卓上实现二代身份证识别,一键实名认证

    @ 目录 前言 场景 开发前准备 android studio 安装 在项目级gradle里添加华为maven仓 在应用级的build.gradle里面加上SDK依赖 在AndroidManifest ...

  6. mybatis 批量删除

    mapper.xml: <update id="delete" parameterType="int"> delete from user_logi ...

  7. python白帽子/黑客/实战编程教程

    Python搜索爬虫抓取超高清视频教程_第一期Python搜索爬虫抓取超高清视频教程_第二期Python搜索爬虫抓取视频教程_第三期Python搜索爬虫抓取视频教程_第四期Python搜索引擎爬虫抓取 ...

  8. 零基础的学习者应该怎么开始学习呢?Python核心知识学习思维分享

    近几年,Python一路高歌猛进,成为最受欢迎的编程语言之一,受到无数编程工作者的青睐. 据悉,Python已经入驻部分小学生教材,可以预见学习Python将成为一项提高自身职业竞争力的必修课.那么零 ...

  9. [php] phpStudy+XDebug配置

    一.配置前说明: 1.phpStudy集成了XDebug扩展,所以不用单独下载XDebug. 2.打开XDebug扩展:其它选项菜单 > PHP扩展 > Xdebug 二.配置步骤: ph ...

  10. 程序选择结构if和switch的定义以及使用方法

       什么是if选择结构 if选择结构是根据条件判断之后在做处理 基本的if选择结构的语法 if(条件){//条件为真则执行代码1,否则不执行  //代码块1 }   if-else选择结构 为什么使 ...