「Luogu2762」太空飞行计划问题

「Luogu2762」太空飞行计划问题

problem

网络流24题
妙啊


题目描述

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

说明

n,m<=50

Solution

这个题,读入就来了个下马威魔改一下快读就是了其实问题也不是很大

然后就是一个经典的最大权闭合子图模型了

Code

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <queue>
#define maxn 55
#define maxm 55
using namespace std;
typedef long long ll;

int flag;
template <typename T>void read(T &t)
{
	t=0;char c=getchar();int f=0;
	while(!isdigit(c)){f|=c=='-';c=getchar();}
	while(isdigit(c)){t=t*10+c-'0';c=getchar();}
	flag|=(c=='\n' || c=='\r');
	if(f)t=-t;
}

const int inf=0x3f3f3f3f;
int n,m,s,t;
int ans;

struct edge
{
	int u,v,w,nxt;
}g[maxm*maxn];

int head[maxn+maxm],ecnt=1;
void eADD(int u,int v,int w)
{
	g[++ecnt].u=u;
	g[ecnt].v=v;
	g[ecnt].w=w;
	g[ecnt].nxt=head[u];
	head[u]=ecnt;
}

int dep[maxn+maxm];
bool BFS()
{
	queue<int> q;
	memset(dep,0,sizeof(dep));
	dep[s]=1;
	q.push(s);
	while(!q.empty())
	{
		int u=q.front();
		q.pop();
		for(register int i=head[u];i;i=g[i].nxt)
		{
			int v=g[i].v;
			if(g[i].w && !dep[v])
			{
				dep[v]=dep[u]+1;
				if(v==t)
					return true;
				q.push(v);
			}
		}
	}
	return false;
}

int dfs(int u,int infl)
{
	if(u==t)
		return infl;
	int rest=infl;
	for(register int i=head[u];i && rest;i=g[i].nxt)
	{
		int v=g[i].v;
		if(dep[v]==dep[u]+1 && g[i].w)
		{
			int flow=dfs(v,min(rest,g[i].w));
			g[i].w-=flow;
			g[i^1].w+=flow;
			rest-=flow;
		}
	}
	return infl-rest;
}

int main()
{
	read(m),read(n);
	s=n+m+1,t=n+m+2;
	for(register int i=1;i<=m;++i)
	{
		int d;
		read(d);
		eADD(s,i,d),eADD(i,s,0),ans+=d;
		flag=false;
		while(!flag)
		{
			read(d);
			eADD(i,m+d,inf),eADD(m+d,i,0);
		}
	}
	for(register int i=1;i<=n;++i)
	{
		int d;
		read(d);
		eADD(m+i,t,d),eADD(t,m+i,0);
	}
	while(BFS())
		ans-=dfs(s,inf);
	for(register int i=1;i<=m;++i)
		if(dep[i])
			printf("%d ",i);
	printf("\n");
	for(register int i=1;i<=n;++i)
		if(dep[m+i])
			printf("%d ",i);
	printf("\n");
	printf("%d",ans);
	return 0;
}
posted @ 2019-01-22 11:57  lizbaka  阅读(320)  评论(0编辑  收藏  举报