Luogu 2762 太空飞行计划 / Libre 6001 「网络流 24 题」太空飞行计划 (网络流,最大流)
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 题」太空飞行计划 (网络流,最大流)的更多相关文章
- LibreOJ #6001. 「网络流 24 题」太空飞行计划 最大权闭合图
#6001. 「网络流 24 题」太空飞行计划 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:Special Judge 上传者: 匿名 提交提交记录统计讨论测 ...
- LOJ6001 - 「网络流 24 题」太空飞行计划
原题链接 Description 有个实验和个仪器,做实验有报酬买仪器有花费.每个实验都需要一些仪器,求最大净收益(实验报酬仪器花费),并输出一组方案. Solution 实验向所需仪器连边,实验的点 ...
- Libre 6013 「网络流 24 题」负载平衡 (网络流,最小费用最大流)
Libre 6013 「网络流 24 题」负载平衡 (网络流,最小费用最大流) Description G 公司有n 个沿铁路运输线环形排列的仓库,每个仓库存储的货物数量不等.如何用最少搬运量可以使n ...
- Libre 6010「网络流 24 题」数字梯形 (网络流,最大费用最大流)
Libre 6010「网络流 24 题」数字梯形 (网络流,最大费用最大流) Description 给定一个由n 行数字组成的数字梯形如下图所示.梯形的第一行有m 个数字.从梯形的顶部的m 个数字开 ...
- Libre 6004 「网络流 24 题」圆桌聚餐(网络流,最大流)
Libre 6004 「网络流 24 题」圆桌聚餐(网络流,最大流) Description 假设有来自n个不同单位的代表参加一次国际会议.每个单位的代表数分别为 ri.会议餐厅共有m张餐桌,每张餐桌 ...
- Libre 6003 「网络流 24 题」魔术球 (网络流,最大流)
Libre 6003 「网络流 24 题」魔术球 (网络流,最大流) Description 假设有n根柱子,现要按下述规则在这n根柱子中依次放入编号为 1,2,3,4......的球. (1)每次只 ...
- LibreOJ #6013. 「网络流 24 题」负载平衡 最小费用最大流 供应平衡问题
#6013. 「网络流 24 题」负载平衡 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 ...
- 【刷题】LOJ 6001 「网络流 24 题」太空飞行计划
题目描述 W 教授正在为国家航天中心计划一系列的太空飞行.每次太空飞行可进行一系列商业性实验而获取利润.现已确定了一个可供选择的实验集合 \(E = \{ E_1, E_2, \cdots, E_m ...
- LibreOJ #6001. 「网络流 24 题」太空飞行计划
\(\quad\) 与网络流有关的最值有三个:最大流,最小费用,最小割.这道题是最小割.想了好久,终于想明白最小割应该怎么用. \(\quad\) 先找出矛盾的事物.在这道题中,两件事是矛盾的:做实验 ...
随机推荐
- 利用IDA6.6进行apk dex代码动态调试
网上公开IDA6.6已经有一段时间,这个版本有个好处就是可以动态调试java代码.正好现在需要动态调试,所以顺便练习一下. 根据android的官方文档,如果要调试一个apk里面的dex代码,必须满足 ...
- 使用 spring-boot-devtools 进行热部署
2019/3/5 更新: 发现热部署不生效,出现页面显示error的错误,然后在 application.properties 中注释了下面两行成功实现热部署(直接删掉也可以) #spring.dev ...
- vue-cli 3.0 实现A-Z字母滑动选择城市列表
项目地址: https://github.com/caochangkui/vue-cli3 项目代码: 城市列表首页: City.vue <template> <div id=&qu ...
- [CF1059E]Split the Tree[贪心+树上倍增]
题意 给定 \(n\) 个节点的树,点有点权 \(w\) ,划分成多条儿子到祖先的链,要求每条链点数不超过 \(L\) ,和不超过 \(S\),求最少划分成几条链. \(n\leq 10^5\) . ...
- SSIS 连接数据
通常情况下,ETL方案需要同时访问两个或多个数据源,并把结果合并为单个数据流,输出到目标表中.为了向目标表中提供统一的数据结构,需要把多个数据源连接在一起.数据连接的另外一种用法,就是根据现有的数据, ...
- Python读取ini配置文件封装方法
读取配置文件 ----rw_ini.py from configparser import ConfigParser def read_config(config_file_path:str): &q ...
- elasticsearch6.6.0安装配置及elasticsearch-head插件安装
一.最小化安装centos7.6 cat /etc/redhat-release 二.配置网络,可以上外网 三.安装常用命令工具,修改系统时区,校对系统时间,关闭selinux,关闭firewalld ...
- EOS开发基础之三:使用cleos命令行客户端操作EOS——关于钱包wallet和账户account
好了,上一节我们已经讲了关于wallet的一些基础操作,基本了解了怎么去创建一个钱包,怎么去查看钱包.上锁和解锁钱包等,这一节咱们就来开始操作账户account吧. 上一节讲到了每一个account都 ...
- PAT甲题题解-1109. Group Photo (25)-(模拟拍照排队)
题意:n个人,要拍成k行排队,每行 n/k人,多余的都在最后一排. 从第一排到最后一排个子是逐渐增高的,即后一排最低的个子要>=前一排的所有人 每排排列规则如下: 1.中间m/2+1为该排最高: ...
- FTP地址
访问不了FTP的同学可以试试用IPv6 地址2001:da8:203:ed5:CEB2:55FF:FE8B:ED1来访问,用户名密码不变.