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

Description

W 教授正在为国家航天中心计划一系列的太空飞行。每次太空飞行可进行一系列商业性实验而获取利润。现已确定了一个可供选择的实验集合E={E1,E2,…,Em},和进行这些实验需要使用的全部仪器的集合I={ I1, I2,…,In }。实验Ej 需要用到的仪器是I的子集Rj∈I。 配置仪器Ik 的费用为ck 美元。实验Ej 的赞助商已同意为该实验结果支付pj 美元。W教授的任务是找出一个有效算法,确定在一次太空飞行中要进行哪些实验并因此而配置哪些仪器才能使太空飞行的净收益最大。这里净收益是指进行实验所获得的全部收入与配置仪器的全部费用的差额。

对于给定的实验和仪器配置情况,编程找出净收益最大的试验计划。

Input

第1行有2个正整数m和n(m,n <= 100)。m是实验数,n是仪器数。

接下来的m行,每行是一个实验的有关数据。第一个数赞助商同意支付该实验的费用;接着是该实验需要用到的若干仪器的编号。最后一行的n个数是配置每个仪器的费用。

Output

第1行是实验编号;第2行是仪器编号;最后一行是净收益。

Sample Input

2 3

10 1 2

25 2 3

5 6 7

Sample Output

1 2

1 2 3

17

Http

Luogu:https://www.luogu.org/problem/show?pid=2762

Libre:https://loj.ac/problem/6001

Source

网络流,最大流

解决思路

这道题要把其转换到网络流模型上不是很好理解。

首先我们来看一看构图

对于每一个实验,从源点到实验连一条流量为赞助商支付的钱的边;对于每一个仪器,从仪器到汇点连一条流量为仪器花费的边。对于每一个实验所需要的仪器,在实验与仪器之间连一条流量无穷大的边。在这张图上跑一边最大流,就可以得到最小的花费,再用总赞助商的支付钱减去这个花费即可。

为什么这样是对的呢?

从源点到实验的边保证了赞助商资助该实验不会超过赞助商的钱,而从仪器到汇点的边则保证了仪器最多只会花费掉这么多的钱

那么最后如何统计答案呢?

由于我们使用的是Dinic求最大流,那么我们可以直接借助层次图的depth数组来求解。因为最后要选取的实验必须是盈利的,所以从源点到盈利的实验的边一定一不满流的,那么也就是说在最后一遍bfs中一定会分配深度,那么我们只要找出depth不为0的实验即可。

同时,由于如果选择做某个实验就要花费其所有需要的仪器,我们可以在求出选择的实验的同时标记出要选择的仪器,最后再输出即可。

另:关于Dinic算法,请移步我的这篇文章

注:Libre的字符串读入似乎有些问题,容易出现RE

代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std; const int maxN=1000;
const int maxM=maxN*maxN*4;
const int inf=147483647; class Edge
{
public:
int v,flow;
}; int n,m;
int cnt=-1;
int Head[maxN];
int Next[maxM];
Edge E[maxM];
int depth[maxN];
int cur[maxN];
int Q[maxM];
bool chose[maxN];//标记某个仪器是否被选择
char str[maxM];//读入时要用到的字符串 void Add_Edge(int u,int v,int flow);
bool bfs();
int dfs(int u,int flow); int main()
{
int sum=0;
memset(Head,-1,sizeof(Head));
scanf("%d%d",&m,&n);
char ch=getchar();
while (ch!='\n')
ch=getchar();
for(int i=1;i<=m;++i)
{
int v;
scanf("%d",&v);
Add_Edge(0,i,v);//连接源点与实验
sum+=v;
memset(str,0,sizeof(str));
cin.getline(str,maxM);
int j=0;
while(sscanf(str+j,"%d",&v)==1)//注意这里的读入
{
if(!v)
j++;
else
Add_Edge(i,v+m,inf);//连接实验与仪器
while(v)
v/=10,j++;
j++;
}
}
/*
for (int i=1;i<=m;i++)//这是原来的字符串读入,会RE,有时还WA
{
int v;
scanf("%d",&v);
sum+=v;
Add_Edge(0,i,v);
ch=getchar();
do
{
while (((ch>'9')||(ch<'0'))&&(ch!='\n'))
ch=getchar();
if (ch=='\n')
break;
v=0;
while ((ch>='0')&&(ch<='9'))
{
v=v*10+ch-48;
ch=getchar();
}
///mcnt++;
Add_Edge(i,v+m,inf);
}
while (1);
}*/
for (int i=1;i<=n;i++)
{
int v;
scanf("%d",&v);
Add_Edge(i+m,n+m+1,v);//连接仪器与汇点
}
int Flow=0;
while (bfs())//Dinic
{
for (int i=0;i<=n+m+1;i++)
cur[i]=Head[i];
while (int di=dfs(0,inf))
Flow+=di;
}
memset(chose,0,sizeof(chose));
for (int i=1;i<=m;i++)//找出选择的实验
if (depth[i]!=-1)
{
printf("%d ",i);
for (int j=Head[i];j!=-1;j=Next[j])//同时标记要选择的仪器
chose[E[j].v-m]=1;
}
cout<<endl;
for (int i=1;i<=n;i++)
if (chose[i]==1)
printf("%d ",i);
cout<<endl;
cout<<sum-Flow<<endl;
return 0;
} void Add_Edge(int u,int v,int flow)//添加边
{
cnt++;
Next[cnt]=Head[u];
Head[u]=cnt;
E[cnt].v=v;
E[cnt].flow=flow; cnt++;
Next[cnt]=Head[v];
Head[v]=cnt;
E[cnt].v=u;
E[cnt].flow=0;
return;
} bool bfs()//构建层次图
{
memset(depth,-1,sizeof(depth));
int h=1,t=0;
Q[1]=0;
depth[0]=1;
do
{
t++;
int u=Q[t];
for (int i=Head[u];i!=-1;i=Next[i])
{
int v=E[i].v;
if ((E[i].flow>0)&&(depth[v]==-1))
{
depth[v]=depth[u]+1;
h++;
Q[h]=v;
}
}
}
while (h!=t);
if (depth[n+m+1]==-1)
return 0;
return 1;
} int dfs(int u,int flow)//增广
{
if (u==n+m+1)
return flow;
for (int &i=cur[u];i!=-1;i=Next[i])
{
int v=E[i].v;
if ((E[i].flow>0)&&(depth[v]==depth[u]+1))
{
int di=dfs(v,min(flow,E[i].flow));
if (di>0)
{
E[i].flow-=di;
E[i^1].flow+=di;
return di;
}
}
}
return 0;
}

Luogu 2762 太空飞行计划 / Libre 6001 「网络流 24 题」太空飞行计划 (网络流,最大流)的更多相关文章

  1. LibreOJ #6001. 「网络流 24 题」太空飞行计划 最大权闭合图

    #6001. 「网络流 24 题」太空飞行计划 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:Special Judge 上传者: 匿名 提交提交记录统计讨论测 ...

  2. LOJ6001 - 「网络流 24 题」太空飞行计划

    原题链接 Description 有个实验和个仪器,做实验有报酬买仪器有花费.每个实验都需要一些仪器,求最大净收益(实验报酬仪器花费),并输出一组方案. Solution 实验向所需仪器连边,实验的点 ...

  3. Libre 6013 「网络流 24 题」负载平衡 (网络流,最小费用最大流)

    Libre 6013 「网络流 24 题」负载平衡 (网络流,最小费用最大流) Description G 公司有n 个沿铁路运输线环形排列的仓库,每个仓库存储的货物数量不等.如何用最少搬运量可以使n ...

  4. Libre 6010「网络流 24 题」数字梯形 (网络流,最大费用最大流)

    Libre 6010「网络流 24 题」数字梯形 (网络流,最大费用最大流) Description 给定一个由n 行数字组成的数字梯形如下图所示.梯形的第一行有m 个数字.从梯形的顶部的m 个数字开 ...

  5. Libre 6004 「网络流 24 题」圆桌聚餐(网络流,最大流)

    Libre 6004 「网络流 24 题」圆桌聚餐(网络流,最大流) Description 假设有来自n个不同单位的代表参加一次国际会议.每个单位的代表数分别为 ri.会议餐厅共有m张餐桌,每张餐桌 ...

  6. Libre 6003 「网络流 24 题」魔术球 (网络流,最大流)

    Libre 6003 「网络流 24 题」魔术球 (网络流,最大流) Description 假设有n根柱子,现要按下述规则在这n根柱子中依次放入编号为 1,2,3,4......的球. (1)每次只 ...

  7. LibreOJ #6013. 「网络流 24 题」负载平衡 最小费用最大流 供应平衡问题

    #6013. 「网络流 24 题」负载平衡 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据   题目描述 ...

  8. 【刷题】LOJ 6001 「网络流 24 题」太空飞行计划

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

  9. LibreOJ #6001. 「网络流 24 题」太空飞行计划

    \(\quad\) 与网络流有关的最值有三个:最大流,最小费用,最小割.这道题是最小割.想了好久,终于想明白最小割应该怎么用. \(\quad\) 先找出矛盾的事物.在这道题中,两件事是矛盾的:做实验 ...

随机推荐

  1. USART_GetITStatus和USART_GetFlagStatus的区别

    USART_GetITStatus()和USART_GetFlagStatus()的区别 都是访问串口的SR状态寄存器,唯一不同是,USART_GetITStatus()会判断中断是否开启,如果没开启 ...

  2. idea 解决 pom.xml 中,maven仓库无法导入的问题(红线)

    只需要用另一篇文章的 maven clean install 功能就行了 idea Cannot Resolve Symbol 问题解决

  3. django在admin后台注册自己创建的数据库表

    django在admin后台注册自己创建的数据库表,这样我们就可以在admin后台看到表结构信息,我们就可以在admin后台快速录入表记录信息 如果没有注册,那么你在登录django自带的admin的 ...

  4. Execute SQL Task 如何返回结果数据集

    Execute Sql Task的Result DataSet 主要有以下四种,当Execute Sql Task返回结果之后,需要使用SSIS Variable 来接收数据. 例子中使用的数据表代码 ...

  5. Jq_select的操作

    jQuery获取Select选择的Text和Value: 语法解释: $("#select_id").change(function(){//code...}); //为Selec ...

  6. numpy 初识(一)

    基本操作: 读取文件(与pandas读取csv相似): import numpy numpy.genfromtxt("word.txt", delimiter=',', dtype ...

  7. Jmeter(十九)_ForEach控制器实现网页爬虫

    一直以来,爬虫似乎都是写代码去实现的,今天像大家介绍一下Jmeter如何实现一个网页爬虫! 龙渊阁测试开发家园 317765580 Jmeter的爬虫原理其实很简单,就是对网页提交一个请求,然后把返回 ...

  8. 使用VSCode调试单个PHP文件

    突然发现是可以使用 VSCode 调试单个 PHP 文件的,今天之前一直没有弄成功,还以为 VSCode 是不能调试单文件呢.这里记录一下今天这个"突然发现"的过程. 开始,是在看 ...

  9. LeetCode-97.交错字符串

    给定三个字符串 s1, s2, s3, 验证 s3 是否是由 s1 和 s2 交错组成的. 示例 1: 输入: s1 = "aabcc", s2 = "dbbca&quo ...

  10. UI Recorder 安装教程(二)

    前言: UI Recorder支持无线native app(Android, iOS)录制, 基于macaca实现:https://macacajs.com/ 本次教程只针对无线native app( ...