2187. 星际转移问题(最大流,最大流判定,分层图)

2024-02-23 23:44

本文主要是介绍2187. 星际转移问题(最大流,最大流判定,分层图),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

活动 - AcWing

由于人类对自然资源的消耗,人们意识到大约在 2300 年之后,地球就不能再居住了。

于是在月球上建立了新的绿地,以便在需要时移民。

令人意想不到的是,2177 年冬由于未知的原因,地球环境发生了连锁崩溃,人类必须在最短的时间内迁往月球。

现有 n 个太空站(编号 1∼n)位于地球与月球之间,且有 m 艘公共交通太空船在其间来回穿梭。

每个太空站可容纳无限多的人,而每艘太空船 i 只可容纳 H[i] 个人。

每艘太空船将周期性地停靠一系列的太空站,例如:(1,3,4) 表示该太空船将周期性地停靠太空站 134134134…。

每一艘太空船从一个太空站驶往任一太空站耗时均为 1。

人们只能在太空船停靠太空站(或月球、地球)时上、下船。

初始时所有人全在地球上,太空船全在初始站,即行驶周期中的第一个站。

试设计一个算法,找出让所有人尽快地全部转移到月球上的运输方案。

输入格式

第 1 行有 3 个正整数 n(太空站个数),m(太空船个数)和 k(需要运送的地球上的人的个数)。

接下来的 m 行给出太空船的信息。第 i+1 行说明太空船 pi。第 1 个数表示 pi 可容纳的人数 H[pi];第 2 个数表示 pi 一个周期停靠的太空站个数 r;随后 r 个数是停靠的太空站的编号 (Si1,Si2,…,Sir),地球用 0 表示,月球用 −1 表示。

时刻 00 时,所有太空船都在初始站,然后开始运行。

在时刻 1,2,3… 等正点时刻各艘太空船停靠相应的太空站。

人只有在 0,1,2… 等正点时刻才能上下太空船。

输出格式

输出让所有人尽快地全部转移到月球上的最短用时。

如果无解,则输出 0。

数据范围

1≤n≤13,
1≤m≤20,
1≤k≤50,
1≤r≤n+2,

输入样例:
2 2 1
1 3 0 1 2
1 3 1 2 -1
输出样例:
5

解析: 

这道题可以枚举天数,建立分成图,每一天就是一层。

这道题不能使用二分,因为建立分层图是根据天数来建的,二分的话天数会波动;而如果枚举天数的话由于每次天数增加 1 ,因此图每次多一层,而且最大流算法可以在之前的残留网络的基础上运算,所以直接在上一次的残留网络上加一层即可。因此枚举天数能使算法更简洁,高效。

#include<iostream>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<math.h>
#include<map>
#include<sstream>
#include<deque>
#include<unordered_map>
#include<unordered_set>
#include<bitset>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
const int N = 1101 * 50 + 10, M = (N + 1100 + 20 * 1101) + 10, INF = 0x3f3f3f3f;
int n, m, k, S, T;
int h[N], e[M], f[M], ne[M], idx;
int q[N], d[N], cur[N];
struct Ship {int h, r, id[30];
}ship[30];
int p[30];int find(int x) {if (p[x] == x)return x;return p[x] = find(p[x]);
}int get(int x, int day) {return day * (n + 2) + x;
}void add(int a, int b, int c) {e[idx] = b, f[idx] = c, ne[idx] = h[a], h[a] = idx++;e[idx] = a, f[idx] = 0, ne[idx] = h[b], h[b] = idx++;
}bool bfs() {int hh = 0, tt = 0;memset(d, -1, sizeof d);q[0] = S, d[S] = 0, cur[S] = h[S];while (hh <= tt) {int t = q[hh++];for (int i = h[t]; i != -1; i = ne[i]) {int j = e[i];if (d[j] == -1 && f[i]) {d[j] = d[t] + 1;cur[j] = h[j];if (j == T)return 1;q[++tt] = j;}}}return 0;
}int find(int u, int limit) {if (u == T)return limit;int flow = 0;for (int i = cur[u]; i != -1 && flow < limit; i = ne[i]) {int j = e[i];cur[u] = i;if (d[j] == d[u] + 1 && f[i]) {int t = find(j, min(f[i], limit - flow));if (!t)d[j] = -1;f[i] -= t, f[i ^ 1] += t, flow += t;}}return flow;
}int dinic() {int ret = 0, flow;while (bfs())while (flow = find(S, INF))ret += flow;return ret;
}int main() {cin >> n >> m >> k;memset(h, -1, sizeof h);S = N - 2, T = N - 1;for (int i = 0; i < 30; i++)p[i] = i;for (int i = 0; i < m; i++) {scanf("%d%d", &ship[i].h, &ship[i].r);for (int j = 0; j < ship[i].r; j++) {int id;scanf("%d", &id);if (id == -1)id = n + 1;ship[i].id[j] = id;if (j) {int x = ship[i].id[j - 1];p[find(x)] = find(id);}}}if (find(0) != find(n + 1))cout << 0 << endl;else {int day = 1, ret = 0;add(S, get(0, 0), k);add(get(n + 1, 0), T, INF);while (1) {add(get(n + 1, day), T, INF);for (int i = 0; i <= n + 1; i++) {add(get(i, day - 1), get(i, day), INF);}for (int i = 0; i < m; i++) {int r = ship[i].r;int a = ship[i].id[(day - 1) % r], b = ship[i].id[(day) % r];add(get(a, day - 1), get(b, day ), ship[i].h);}ret += dinic();if (ret >= k)break;day++;}cout << day << endl;}return 0;
}

这篇关于2187. 星际转移问题(最大流,最大流判定,分层图)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/740309

相关文章

mybatis和mybatis-plus设置值为null不起作用问题及解决

《mybatis和mybatis-plus设置值为null不起作用问题及解决》Mybatis-Plus的FieldStrategy主要用于控制新增、更新和查询时对空值的处理策略,通过配置不同的策略类型... 目录MyBATis-plusFieldStrategy作用FieldStrategy类型每种策略的作

linux下多个硬盘划分到同一挂载点问题

《linux下多个硬盘划分到同一挂载点问题》在Linux系统中,将多个硬盘划分到同一挂载点需要通过逻辑卷管理(LVM)来实现,首先,需要将物理存储设备(如硬盘分区)创建为物理卷,然后,将这些物理卷组成... 目录linux下多个硬盘划分到同一挂载点需要明确的几个概念硬盘插上默认的是非lvm总结Linux下多

Python Jupyter Notebook导包报错问题及解决

《PythonJupyterNotebook导包报错问题及解决》在conda环境中安装包后,JupyterNotebook导入时出现ImportError,可能是由于包版本不对应或版本太高,解决方... 目录问题解决方法重新安装Jupyter NoteBook 更改Kernel总结问题在conda上安装了

pip install jupyterlab失败的原因问题及探索

《pipinstalljupyterlab失败的原因问题及探索》在学习Yolo模型时,尝试安装JupyterLab但遇到错误,错误提示缺少Rust和Cargo编译环境,因为pywinpty包需要它... 目录背景问题解决方案总结背景最近在学习Yolo模型,然后其中要下载jupyter(有点LSVmu像一个

解决jupyterLab打开后出现Config option `template_path`not recognized by `ExporterCollapsibleHeadings`问题

《解决jupyterLab打开后出现Configoption`template_path`notrecognizedby`ExporterCollapsibleHeadings`问题》在Ju... 目录jupyterLab打开后出现“templandroidate_path”相关问题这是 tensorflo

如何解决Pycharm编辑内容时有光标的问题

《如何解决Pycharm编辑内容时有光标的问题》文章介绍了如何在PyCharm中配置VimEmulator插件,包括检查插件是否已安装、下载插件以及安装IdeaVim插件的步骤... 目录Pycharm编辑内容时有光标1.如果Vim Emulator前面有对勾2.www.chinasem.cn如果tools工

最长公共子序列问题的深度分析与Java实现方式

《最长公共子序列问题的深度分析与Java实现方式》本文详细介绍了最长公共子序列(LCS)问题,包括其概念、暴力解法、动态规划解法,并提供了Java代码实现,暴力解法虽然简单,但在大数据处理中效率较低,... 目录最长公共子序列问题概述问题理解与示例分析暴力解法思路与示例代码动态规划解法DP 表的构建与意义动

Java多线程父线程向子线程传值问题及解决

《Java多线程父线程向子线程传值问题及解决》文章总结了5种解决父子之间数据传递困扰的解决方案,包括ThreadLocal+TaskDecorator、UserUtils、CustomTaskDeco... 目录1 背景2 ThreadLocal+TaskDecorator3 RequestContextH

关于Spring @Bean 相同加载顺序不同结果不同的问题记录

《关于Spring@Bean相同加载顺序不同结果不同的问题记录》本文主要探讨了在Spring5.1.3.RELEASE版本下,当有两个全注解类定义相同类型的Bean时,由于加载顺序不同,最终生成的... 目录问题说明测试输出1测试输出2@Bean注解的BeanDefiChina编程nition加入时机总结问题说明

关于最长递增子序列问题概述

《关于最长递增子序列问题概述》本文详细介绍了最长递增子序列问题的定义及两种优化解法:贪心+二分查找和动态规划+状态压缩,贪心+二分查找时间复杂度为O(nlogn),通过维护一个有序的“尾巴”数组来高效... 一、最长递增子序列问题概述1. 问题定义给定一个整数序列,例如 nums = [10, 9, 2