网络流 24题 太空飞行问题

太空飞行计划

题目描述

输入格式

文件第1行有2个正整数m和n。m是实验数,n是仪器数。接下来的m行,每行是一个实验的有关数据。第一个数赞助商同意支付该实验的费用;接着是该实验需要用到的若干仪器的编号。最后一行的n个数是配置每个仪器的费用。
(1<=n, m<=50)

输出格式

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

输入样例

23 
10 1 2 
25 2 3 
5 6 7

输出样例 2209.out

12 
1 2 3 
17

关于这题的吐槽:

    最坑的不是构图or输出方案,这题的输入就够人磨一阵子的了。因为在输入了同意支付这个实验的费用以后,接的是若干台仪器。若干……简直不想吐槽了,逼得只能用字符串s直接输入这一整行,然后再慢慢分解。结果单单输入就直接占了50多行的代码位置。

解题思想:

    关于这题的构图方法要感谢ywq同学,讲得挺通俗易懂。从收益上考虑。如果不做这个实验,那就得不到这笔经费,会有所损失;如果做这台实验,虽然经费的支柱,但是要买仪器,同样会损失。而我们要做的就是看割哪一条边会损失最小。

构图:

    把实验编号放在左边,与节点s连接,仪器编号放右边,与节点t连接。跑一次最小割,得出来的就是消费最大的选择。

注意,图中的仪器编号已经向后移了m。

输出方案:

    最后在残余网络中,查看,哪些边被格调,即可以相连的两条边之间,v[now]是被选的(赋值为1),v[to]是不被选的,假设to是实验,那么说明不做这个实验;如果是仪器,那么说明选择这台仪器。

那么怎么区别是实验还是仪器呢?只要看它隔开的那条边,即to是否为t,如果为,那么说明是仪器,把这台now仪器标记为不取,否则,说明是实验,那么把to实验标记为不取。

为了更清晰地表示为什么实验是to,仪器是now,回到上面的图,复原一下会是怎么割的,割掉的说明不取会更好。

看图分析就比较直观了。

代码如下:

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
using namespace std;
const int  maxn=205,oo=1000000000;
int m,n,s,t,ans,ma[maxn],ex[maxn],v[maxn],head[maxn],c[maxn],p[maxn],cur=-1;
string ss;
struct space
{
	int to,next,va,type;
}edge[maxn*maxn];

void add(int from,int to,int va,int type)
{
	cur++;
	edge[cur].to=to;
	edge[cur].va=va;
	edge[cur].type=type;
	edge[cur].next=head[from];
	head[from]=cur;
}
void init()//此处是麻烦的输入
{
	cin>>m>>n;
	s=0,t=m+n+1;

	memset(head,-1,sizeof(head));
	for(int i=1;i<=m+1;i++)
	{
		getline(cin,ss);//输入字符串
		if(i>1)
		{

			int size=ss.size(),j=0;
			while(ss[j]>=‘0‘&&ss[j]<=‘9‘)
			{
				p[i-1]=p[i-1]*10+(ss[j]-‘0‘);
				j++;
			}//存下资助的金额
			int num=0;
			j++;
			while(j<size)
			{
				if(ss[j]==‘ ‘ || ss[j]==‘\n‘ || ss[j] == ‘\r‘)
				{
					add(i-1,num+m,oo,0);
					add(num+m,i-1,0,1);
					num=0;
				}
				else num=num*10+(ss[j]-‘0‘);
				j++;
			}//存需要哪些机器
		}
	}
	for(int i=m+1;i<=m+n;i++) cin>>c[i];

	for(int i=1;i<=m;i++)
	{
		ans=ans+p[i];
		add(s,i,p[i],0);
		add(i,s,0,1);
	}//资助金额与s相连
	for(int i=m+1;i<=m+n;i++)
	{
		add(i,t,c[i],0);
		add(t,i,0,1);
	}//仪器与t相连
}

int dfs(int now,int mi)//最大流(最小割)
{
	if(now==t) return mi;
	v[now]=1;
	int h=head[now];
	while(h!=-1)
	{
		int to=edge[h].to,va=edge[h].va;
		if(v[to]==0&&va!=0)
		{
			int k;
			k=dfs(to,min(va,mi));
			if(k!=0)
			{
				edge[h].va-=k;
				if(edge[h].type==0) edge[h+1].va+=k;
				else edge[h-1].va+=k;
				return k;
			}
		}
		h=edge[h].next;
	}
	return 0;
}

void check(int now)//扫一次残余网络。
{
	int h=head[now];
	while(h!=-1)
	{
		int to=edge[h].to,type=edge[h].type;
		if(type==0)
		{
			if(v[now]==1&&v[to]==0)//查看哪些仪器或实验是不用的
			{
				if(to==t) ma[now-m]=1;
				else ex[to]=1;
			}
			check(to);
		}
		h=edge[h].next;
	}
}

void start()//输出
{
	check(0);
	for(int i=1;i<=m;i++)
	{
		if(ex[i]!=1) cout<<i<<" ";
	}
	cout<<endl;
	for(int i=1;i<=n;i++)
	{
		if(ma[i]==1) cout<<i<<" ";
	}
	cout<<endl;
}

int main()
{
	freopen("2209.in","r",stdin);
	freopen("2209.out","w",stdout);
	init();

	while(1)
	{
		memset(v,0,sizeof(v));
		int res;
		res=dfs(0,oo);
		if(res==0) break;
		ans-=res;
	}
	start();
	cout<<ans<<endl;
	return 0;
}
时间: 2024-10-04 10:13:39

网络流 24题 太空飞行问题的相关文章

[网络流24题] 太空飞行计划 (最大权闭合子图---网络最大流)

727. [网络流24题] 太空飞行计划 ★★☆ 输入文件:shuttle.in 输出文件:shuttle.out 简单对比 时间限制:1 s 内存限制:128 MB [问题描述] W 教授正在为国家航天中心计划一系列的太空飞行.每次太空飞行可进行一系列商业性实验而获取利润.现已确定了一个可供选择的实验集合E={E1,E2,…,Em},和进行这些实验需要使用的全部仪器的集合I={ I1, I2,…,In }.实验Ej 需要用到的仪器是I的子集Rj∈I.配置仪器Ik 的费用为ck 美元.实验Ej

[网络流24题] 太空飞行计划(cogs 727)

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

[网络流24题]太空飞行计划问题

Description $W$教授正在为国家航天中心计划一系列的太空飞行.每次太空飞行可进行一系列商业 性实验而获取利润.现已确定了一个可供选择的实验集合$E={E_1,E_2,...,E_m}$,和进行这些实验需要使用的全部仪器的集合$I={I_1,I_2,...,I_n}$.实验$E_j$需要用到的仪器是$I$的子集$R_j\;\in\;I$.配置仪器$I_k$的费用为$c_k$美元.实验$E_j$的赞助商已同意为该实验结果支付$p_j$美元.$W$教授的任务是确定在一次太空飞行中要进行哪些

[luogu2762] [网络流24题] 太空飞行计划问题

传送门 一道最大权闭合子图的题目.直接建图跑dinic就行了,答案为正权点-最大流. 那剩下的问题就是如果知道哪些点被选进最大权闭合子图. 我们知道一个简单割对应了一个闭合子图,当这个简单割是最小割,即最大流,其与\(s\)相关的点即为闭合子图. #include <queue> #include <cstdio> #include <cstring> #include <algorithm> #define MAXN 105 #define INF 214

题解:线性规划与网络流24题 T2 太空飞行计划问题

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

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

#6001. 「网络流 24 题」太空飞行计划 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:Special Judge 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 W 教授正在为国家航天中心计划一系列的太空飞行.每次太空飞行可进行一系列商业性实验而获取利润.现已确定了一个可供选择的实验集合 E={E1,E2,?,Em} E = \{ E_1, E_2, \cdots, E_m \}E={E?1??,E?2??,?,E?m??},和进行这些实验

线性规划与网络流24题第2题 太空飞行计划 最小割

/** 题目: 线性规划与网络流24题第2题 太空飞行计划 最小割 链接:http://www.cogs.pro/cogs/problem/problem.php?pid=727 题意:lv 思路:最大点权独立集(点集中任意两个点没有边相连,且点权和最大)=点权总和-最小点权覆盖集. 将实验和仪器看做节点. 实验放在二分图的左边, s->x, cap = 实验利润. 仪器放在右边, x->t, cap = 仪器费用. 如果实验u的进行需要仪器v,u->v, cap = INF. ans

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

「网络流24题」2. 太空飞行计划问题 <题目链接> 最大权闭合子图. 源点与实验连边权为实验费用的有向边: 仪器与汇点连边权为仪器费用的有向边: 实验与仪器之间连边权为INF的有向边. 答案为所有与源点相连的边的边权和减去图的最小割. 证明见国集队员胡伯涛论文<最小割模型在信息学竞赛中的应用>. 输出路径时,最后一次层次图中: 与源点相连的点即选做的实验:与汇点相连的点即选用的仪器. 注意 ·读入数据时,读到空格继续,否则停止. ·仪器部分的点权+50,避免两部点权相同. #in

网络流24题刷题记录

题目一:飞行员配对方案问题 一群飞行员和另一群飞行员之间有的可以配对,有的不能配对,求最多可以配多少对? 典型二分图最大匹配问题.可以用匈牙利算法 或者 加上源点汇点之后跑最大流.[感觉第二个打错的概率还低一些]. [还是介绍一下匈牙利算法吧][看白书大法好!] 从左边(s集)一个未盖点出发(还有没有和任何人匹配的点)出发,顺次经过未选边->选边->未选边.....[这样的路叫做交替路] 如果路径当中经过一个未盖点[这样的交替路叫增广路]...那么将所有的选边变成不选,不选的边选上,就可以多一