太空飞行计划问题

问题描述

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

编程任务

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

数据输入

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

结果输出

程序运行结束时,将最佳实验方案输出到文件output.txt中。第1行是实验编号;第2行是仪器编号;最后一行是净收益。

输入文件示例input.txt

2 3

10 1 2

25 2 3

5 6 7

输出文件示例output.txt

1 2 

1 2 3

17

分析:

我们可以用最大权闭合图模型建图,把实验看作二分图的X集,仪器看作二分图的Y集。加个S,加个T,S向所有X集连边,边权为该实验的收入。所有仪器向T连边,边权为改仪器的花费。所有实验向其依赖的仪器连边,边权为inf

然后求最小割,答案就是所有实验收入之和Total - maxflow。

       .......接下来让我们考虑一下为何能如此建图。

定义一个割划分出的S集为一个解,则割集容量之和为未选的实验的收入 + 被选的仪器的花费。这样Total – maxflow就代表被选的实验收入– 被选的仪器花费。

这样问题就转化成了最大化(Total – maxflow) ,也就是最小化maxflow。

       So......you know.........

Code:

#include <cstdio>
#include <cstring>
using namespace std; const int inf = 1 << 30;
const int maxn = 1010;
const int maxm = 2020;
inline int min(int a,int b) {return a < b ? a : b;} int tot;
struct Edge
{
int v,w,nxt;
}e[maxm];
int head[maxn];
int d[maxn],q[maxn];
int sta,end; inline void addedge(int u,int v,int d)
{
e[tot].v = v,e[tot].w = d,e[tot].nxt = head[u],head[u] = tot ++;
e[tot].v = u,e[tot].w = 0,e[tot].nxt = head[v],head[v] = tot ++;
} inline int bfs()
{
memset(d,-1,sizeof(d));
int r = d[q[0] = sta] = 0;
for(int l = 0;l <= r;l ++)
for(int k = head[q[l]]; ~k ;k = e[k].nxt)
if(e[k].w && !~d[e[k].v])
d[q[++ r] = e[k].v] = d[q[l]] + 1;
return ~d[end];
} int find(int x,int low)
{
if(x == end) return low;
int a;
for(int k = head[x]; ~k ;k = e[k].nxt)
if(e[k].w && d[e[k].v] == d[x] + 1 && (a = find(e[k].v,min(low,e[k].w))))
{
e[k].w -= a;
e[k ^ 1].w += a;
return a;
}
return 0;
} int dinic()
{
int ret = 0,t;
while(bfs())
while(t = find(sta,inf)) ret += t;
return ret;
} bool bLineBreak;
void scan(int & n)
{
char c; n = 0; bLineBreak = 0;
while(c = getchar(),c < '0' || c > '9') if(c == '\n') bLineBreak = 1;
n = c - '0';
while(c = getchar(),(c >= '0' && c <= '9')) n = n * 10 + c - '0';
if(c == '\n') bLineBreak = 1;
} inline void debug_dinic()
{
int n,m;
scanf("%d%d",&n,&m);
sta = 0,end =1;
memset(head,-1,sizeof(head));
while(m --)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
addedge(u,v,w);
}
printf(" %d \n",dinic());
} inline void debug_scan()
{
int n;
do
{
scan(n);
printf("%d\n",n);
} while(!bLineBreak);
} int experiment[maxn],vis[maxn]; int main()
{
int m,n,sum = 0;
sta = 0,end = 1;
scanf("%d%d",&m,&n);
memset(head,-1,sizeof(head));
for(int i = 0;i < m;i ++)
{
int val,id;
scanf("%d",&val);
addedge(sta,i + 2,val),sum += val;
do
{
scan(id);
addedge(i + 2,m + 1 + id,inf);
} while(!bLineBreak);
}
for(int i = 0;i < n;i ++)
{
int cost;
scanf("%d",&cost);
addedge(m + 2 + i,end,cost);
}
int ans = sum - dinic();
int cnt = 0;
for(int k = head[0]; ~k ;k = e[k].nxt) if(e[k].w)
{
int id = e[k].v;
experiment[cnt ++] = id;
printf("%d ",id - 1);
}
putchar('\n');
for(int i = 0;i < cnt;i ++)
{
for(int k = head[experiment[i]]; ~k ;k = e[k].nxt)
{
int v = e[k].v;
if(vis[v]) continue;
vis[v] = 1;
if(!e[head[v]].w) printf("%d ",e[k].v - 1 - m);
}
}
printf("\n%d",ans);
return 0;
}

题解:线性规划与网络流24题 T2 太空飞行计划问题的更多相关文章

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

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

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

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

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

    Luogu 2762 太空飞行计划 / Libre 6001 「网络流 24 题」太空飞行计划 (网络流,最大流) Description W 教授正在为国家航天中心计划一系列的太空飞行.每次太空飞行 ...

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

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

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

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

  6. [Cogs727] [网络流24题#2] 太空飞行计划 [网络流,最小割]

    建图:源点—(w[i])—>实验—(∞)—>仪器—(cost[i])—>汇点, 如果该实验造成收益,则仪器到汇点的边在最小割中, 如果该实验造成损失,则源点到实验的边在最小割中, 故 ...

  7. 【PowerOJ1737&网络流24题】太空飞行计划问题(最小割)

    题意: 思路: #include<bits/stdc++.h> using namespace std; typedef long long ll; typedef unsigned in ...

  8. 【线性规划与网络流 24题】已完成(3道题因为某些奇怪的原因被抛弃了QAQ)

    写在前面:SDOI2016 Round1滚粗后蒟蒻开始做网络流来自我拯救(2016-04-11再过几天就要考先修课,现在做网络流24题貌似没什么用←退役节奏) 做的题目将附上日期,见证我龟速刷题. 1 ...

  9. 【题解】【网络流24题】航空路线问题 [P2770] [Loj6122]

    [题解][网络流24题]航空路线问题 [P2770] [Loj6122] 传送门:航空路线问题 \([P2770]\) \([Loj6122]\) [题目描述] 给出一张有向图,每个点(除了起点 \( ...

随机推荐

  1. Struts 2的下载和安装

    一.为Web应用增加Struts 2支持 下载和安装Struts 2步骤: 登录http://struts.apache.org/download.cgi站点,下载Struts 2的最新版,下载时有以 ...

  2. 吴裕雄--天生自然ShellX学习笔记:Shell 变量

    定义变量时,变量名不加美元符号($,PHP语言中变量需要),如: your_name="runoob.com" 注意,变量名和等号之间不能有空格,这可能和你熟悉的所有编程语言都不一 ...

  3. 吴裕雄--天生自然 PHP开发学习:高级

    <?php echo date("Y/m/d") . "<br>"; echo date("Y.m.d") . " ...

  4. 黑马_13 Spring Boot:04.spring boot 配置文件

    13 Spring Boot: 01.spring boot 介绍&&02.spring boot 入门 04.spring boot 配置文件 05.spring boot 整合其他 ...

  5. 个性化bash

    zsh/on-my-zsh Ubuntu,deepin, 等可以使用  apt install 的系统  apt install zsh 一般就可以自动安装 RedHat(Fedora,Centos) ...

  6. Python 安装zbar-py时出现 无法打开包括文件: “unistd.h” no such file or directory

    问题 途中使用的命令是cl.exe,在执行命令的时候找不到对应的unistd.h文件. unistd.h是Unix系统的文件,因此,十有八九,使用的是Windows系统.下面的代码可以修复,但是如果修 ...

  7. 14. docker 网络 docker bridge0 详解

    1.创建一个 container docker run -d --name test1 busybox /bin/sh -c "while true; do sleep 3600; done ...

  8. LCA 最近公共祖先 Tarjan(离线)算法的基本思路及其算法实现

    首先是最近公共祖先的概念(什么是最近公共祖先?): 在一棵没有环的树上,每个节点肯定有其父亲节点和祖先节点,而最近公共祖先,就是两个节点在这棵树上深度最大的公共的祖先节点. 换句话说,就是两个点在这棵 ...

  9. sbt 设置

    修改 sbtopts for shell # zkk -sbt-dir D:/DATA/.sbt -sbt-boot D:/DATA/.sbt/boot -ivy D:/DATA/.ivy2 修改 s ...

  10. Python语言学习前提:基础语法

    一.变量 1.变量:存储数据.存储数据需要对应内存空间,基于变量的数据类型,解释器会分配指定内存,决定什么数据被存储到内存中. 变量数据类型:整数.小数.字符. 2.变量赋值:变量在使用前必须赋值,赋 ...