题目描述

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. Thymeleaf+SpringBoot+SpringDataJPA实现的中小医院信息管理系统

    项目简介 项目来源于:https://gitee.com/sensay/hisystem 作者介绍 本系统是基于Thymeleaf+SpringBoot+SpringDataJPA实现的的中小医院信息 ...

  2. vue2.x学习笔记(十八)

    接着前面的内容:https://www.cnblogs.com/yanggb/p/12629705.html. 处理边界情况 这里记录的都是和处理边界情况有关的功能,即一些需要对vue的规则做一些小调 ...

  3. linux CVE-2019-13272 本地特权漏洞

    漏洞描述 在5.1.17之前的Linux内核中,kernel / ptrace.c中的ptrace_link错误地处理了想要创建ptrace关系的进程的凭据记录,这允许本地用户通过利用父子的某些方案来 ...

  4. 编程是要偷懒的--option简练写法

    没改前: if(!empty($search)){ $where['personal_name'] = array('like','%'. $search . '%'); $this -> as ...

  5. linux--配置开发环境 --Apache篇

    现在我的的linux服务器上一般都是使用:Apache 和  Nginx 这两种配置. 你现在安装好了,启动了,也无法通过你服务器绑定的网址访问你的网站. 这是你可以通过这个命令查看一下你的80端口: ...

  6. python 开发一款图片压缩工具(四):上传图床

    上一篇使用了 pngquant 图片压缩工具进行压缩,并通过 click 命令行工具构建了 picom 包.这篇的主要功能是实现图片上传. 图片上传功能的实现 通过 pngquant 压缩图片后,得到 ...

  7. icmp的抓包分析

    ICMP(Internet Control Message Protocol)Internet控制报文协议.它是TCP/IP协议簇的一个子协议,用于在IP主机.路由器之间传递控制消息.控制消息是指网络 ...

  8. Qt 的日期 时间

    QDateTime 的构造函数,有参数是QDate的.这样就可以把日期转化成 QDateTime. QDateTime.toTime_t() 可以转化成 Unix 时间.

  9. Spring Security OAuth2 笔记(一)

    关于 refresh_token refresh_token 主要是用来在 access_token 快要过期的时候,对 access_token 进行一个刷新,生成一个新的 access_token ...

  10. Spring MVC 中的http Caching

    文章目录 过期时间 Last-Modified ETag Spring ETag filter Spring MVC 中的http Caching Cache 是HTTP协议中的一个非常重要的功能,使 ...