【C++BFS算法】2039. 网络空闲的时刻

本文涉及知识点

C++BFS算法
分治法

LeetCode2039. 网络空闲的时刻

给你一个有 n 个服务器的计算机网络,服务器编号为 0 到 n - 1 。同时给你一个二维整数数组 edges ,其中 edges[i] = [ui, vi] 表示服务器 ui 和 vi 之间有一条信息线路,在 一秒 内它们之间可以传输 任意 数目的信息。再给你一个长度为 n 且下标从 0 开始的整数数组 patience 。
题目保证所有服务器都是 相通 的,也就是说一个信息从任意服务器出发,都可以通过这些信息线路直接或间接地到达任何其他服务器。
编号为 0 的服务器是 主 服务器,其他服务器为 数据 服务器。每个数据服务器都要向主服务器发送信息,并等待回复。信息在服务器之间按 最优 线路传输,也就是说每个信息都会以 最少时间 到达主服务器。主服务器会处理 所有 新到达的信息并 立即 按照每条信息来时的路线 反方向 发送回复信息。
在 0 秒的开始,所有数据服务器都会发送各自需要处理的信息。从第 1 秒开始,每 一秒最 开始 时,每个数据服务器都会检查它是否收到了主服务器的回复信息(包括新发出信息的回复信息):

如果还没收到任何回复信息,那么该服务器会周期性 重发 信息。数据服务器 i 每 patience[i] 秒都会重发一条信息,也就是说,数据服务器 i 在上一次发送信息给主服务器后的 patience[i] 秒 后 会重发一条信息给主服务器。
否则,该数据服务器 不会重发 信息。
当没有任何信息在线路上传输或者到达某服务器时,该计算机网络变为 空闲 状态。
请返回计算机网络变为 空闲 状态的 最早秒数 。
示例 1:
在这里插入图片描述

输入:edges = [[0,1],[1,2]], patience = [0,2,1]
输出:8
解释:
0 秒最开始时,

  • 数据服务器 1 给主服务器发出信息(用 1A 表示)。
  • 数据服务器 2 给主服务器发出信息(用 2A 表示)。

1 秒时,

  • 信息 1A 到达主服务器,主服务器立刻处理信息 1A 并发出 1A 的回复信息。
  • 数据服务器 1 还没收到任何回复。距离上次发出信息过去了 1 秒(1 < patience[1] = 2),所以不会重发信息。
  • 数据服务器 2 还没收到任何回复。距离上次发出信息过去了 1 秒(1 == patience[2] = 1),所以它重发一条信息(用 2B 表示)。

2 秒时,

  • 回复信息 1A 到达服务器 1 ,服务器 1 不会再重发信息。
  • 信息 2A 到达主服务器,主服务器立刻处理信息 2A 并发出 2A 的回复信息。
  • 服务器 2 重发一条信息(用 2C 表示)。

    4 秒时,
  • 回复信息 2A 到达服务器 2 ,服务器 2 不会再重发信息。

    7 秒时,回复信息 2D 到达服务器 2 。

从第 8 秒开始,不再有任何信息在服务器之间传输,也不再有信息到达服务器。
所以第 8 秒是网络变空闲的最早时刻。
示例 2:

example 2

输入:edges = [[0,1],[0,2],[1,2]], patience = [0,10,10]
输出:3
解释:数据服务器 1 和 2 第 2 秒初收到回复信息。
从第 3 秒开始,网络变空闲。

提示:

n == patience.length
2 <= n <= 105
patience[0] == 0
对于 1 <= i < n ,满足 1 <= patience[i] <= 105
1 <= edges.length <= min(105, n * (n - 1) / 2)
edges[i].length == 2
0 <= ui, vi < n
ui != vi
不会有重边。
每个服务器都直接或间接与别的服务器相连。

C++ BFS

各从服务器发送的消息互相不影响,故用分治法:分别处理各服务器发送的消息。
假定服务期cur记录0号服务器距离d,则0秒的消息2d秒收到,即2d秒及之后不会收到消息。最后一条消息发送时间t1为:
t1 = (2d-1)/patience[i]*patience[i] cur服务区空闲的时间是t2=t1+2 × \times × d +1
结果是:max(t2)
BFS层次讲得比较多了,就不再赘述了。

代码

核心代码

class CNeiBo
{
public:	
	static vector<vector<int>> Two(int n, vector<vector<int>>& edges, bool bDirect, int iBase = 0) 
	{
		vector<vector<int>>  vNeiBo(n);
		for (const auto& v : edges)
		{
			vNeiBo[v[0] - iBase].emplace_back(v[1] - iBase);
			if (!bDirect)
			{
				vNeiBo[v[1] - iBase].emplace_back(v[0] - iBase);
			}
		}
		return vNeiBo;
	}	
	static vector<vector<std::pair<int, int>>> Three(int n, vector<vector<int>>& edges, bool bDirect, int iBase = 0)
	{
		vector<vector<std::pair<int, int>>> vNeiBo(n);
		for (const auto& v : edges)
		{
			vNeiBo[v[0] - iBase].emplace_back(v[1] - iBase, v[2]);
			if (!bDirect)
			{
				vNeiBo[v[1] - iBase].emplace_back(v[0] - iBase, v[2]);
			}
		}
		return vNeiBo;
	}	
	static vector<vector<int>> Mat(vector<vector<int>>& neiBoMat)
	{
		vector<vector<int>> neiBo(neiBoMat.size());
		for (int i = 0; i < neiBoMat.size(); i++)
		{
			for (int j = i + 1; j < neiBoMat.size(); j++)
			{
				if (neiBoMat[i][j])
				{
					neiBo[i].emplace_back(j);
					neiBo[j].emplace_back(i);
				}
			}
		}
		return neiBo;
	}
};

class CBFSLeve {
public :
	static vector<int> Leve(const vector<vector<int>>& neiBo, vector<int> start) {
		vector<int> leves(neiBo.size(), -1);
		for (const auto& s : start) {
			leves[s] = 0;
		}
		for (int i = 0; i < start.size(); i++) {
			for (const auto& next : neiBo[start[i]]) {
				if (-1 != leves[next]) { continue; }
				leves[next] = leves[start[i]]+1;
				start.emplace_back(next);
			}
		}
		return leves;
	}
};

	class Solution {
		public:
			int networkBecomesIdle(vector<vector<int>>& edges, vector<int>& patience) {
				auto neiBo = CNeiBo::Two(patience.size(), edges, false);
				auto leves = CBFSLeve::Leve(neiBo, { 0 });
				int ret = 0;
				for (int i = 1; i < leves.size();i++) {
					const int t1 = leves[i] * 2 - 1;
					const int t2 = t1 / patience[i] * patience[i];
					ret = max(ret, t2 + leves[i] * 2 + 1);
				}
				return ret;
			}
		};

单元测试

vector<vector<int>> edges;
		vector<int> patience;
		TEST_METHOD(TestMethod11)
		{
			edges = { {0,1},{1,2} }, patience = { 0,2,1 };
			auto res = Solution().networkBecomesIdle(edges, patience);
			AssertEx(res, 8);
		}
		TEST_METHOD(TestMethod12)
		{
			edges = { {0,1},{0,2},{1,2} }, patience = { 0,10,10 };
			auto res = Solution().networkBecomesIdle(edges, patience);
			AssertEx(res, 3);
		}

扩展阅读

我想对大家说的话
工作中遇到的问题,可以按类别查阅鄙人的算法文章,请点击《算法与数据汇总》。
学习算法:按章节学习《喜缺全书算法册》,大量的题目和测试用例,打包下载。重视操作
有效学习:明确的目标 及时的反馈 拉伸区(难度合适) 专注
闻缺陷则喜(喜缺)是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。
如果程序是一条龙,那算法就是他的是睛
失败+反思=成功 成功+反思=成功

视频课程

先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771
如何你想快速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176

测试环境

操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。

  • 19
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 10
    评论
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

闻缺陷则喜何志丹

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值