【C++BFS算法】2192. 有向无环图中一个节点的所有祖先
创始人
2024-11-04 14:32:59
0

本文涉及知识点

C++BFS算法

LeetCode2192. 有向无环图中一个节点的所有祖先

给你一个正整数 n ,它表示一个 有向无环图 中节点的数目,节点编号为 0 到 n - 1 (包括两者)。
给你一个二维整数数组 edges ,其中 edges[i] = [fromi, toi] 表示图中一条从 fromi 到 toi 的单向边。
请你返回一个数组 answer,其中 answer[i]是第 i 个节点的所有 祖先 ,这些祖先节点 升序 排序。
如果 u 通过一系列边,能够到达 v ,那么我们称节点 u 是节点 v 的 祖先 节点。
示例 1:

输入:n = 8, edgeList = [[0,3],[0,4],[1,3],[2,4],[2,7],[3,5],[3,6],[3,7],[4,6]]
输出:[[],[],[],[0,1],[0,2],[0,1,3],[0,1,2,3,4],[0,1,2,3]]
解释:
上图为输入所对应的图。

  • 节点 0 ,1 和 2 没有任何祖先。
  • 节点 3 有 2 个祖先 0 和 1 。
  • 节点 4 有 2 个祖先 0 和 2 。
  • 节点 5 有 3 个祖先 0 ,1 和 3 。
  • 节点 6 有 5 个祖先 0 ,1 ,2 ,3 和 4 。
  • 节点 7 有 4 个祖先 0 ,1 ,2 和 3 。
    示例 2:

输入:n = 5, edgeList = [[0,1],[0,2],[0,3],[0,4],[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]]
输出:[[],[0],[0,1],[0,1,2],[0,1,2,3]]
解释:
上图为输入所对应的图。

  • 节点 0 没有任何祖先。
  • 节点 1 有 1 个祖先 0 。
  • 节点 2 有 2 个祖先 0 和 1 。
  • 节点 3 有 3 个祖先 0 ,1 和 2 。
  • 节点 4 有 4 个祖先 0 ,1 ,2 和 3 。

提示:
1 <= n <= 1000
0 <= edges.length <= min(2000, n * (n - 1) / 2)
edges[i].length == 2
0 <= fromi, toi <= n - 1
fromi != toi
图中不会有重边。
图是 有向 且 无环 的。

C++BFS

本问题    ⟺    \iff ⟺ 求各节点的后代,BFS各节点的层次,层次不是-1,就是后代。求一个节点后代的时间复杂度:O(m) ,m = edges.length,总时间复杂度为:O(nm)。 空间复杂度:O(m),每次求节点后代,都重新分配内存。

代码

核心代码

class CBFSLeve { public : 	static vector Leve(const vector>& neiBo, vector start) { 		vector 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 CNeiBo { public:	 	static vector> Two(int n, vector>& edges, bool bDirect, int iBase = 0)  	{ 		vector>  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>> Three(int n, vector>& edges, bool bDirect, int iBase = 0) 	{ 		vector>> 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> Mat(vector>& neiBoMat) 	{ 		vector> 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 Solution { 		public: 			vector> getAncestors(int n, vector>& edges) { 				auto neiBo = CNeiBo::Two(n, edges, true); 				vector> ret(n); 				for (int i = 0; i < n; i++) { 					auto leve = CBFSLeve::Leve(neiBo, { i }); 					for (int j = 0; j < leve.size(); j++) { 						if (leve[j]<=0) { continue; } 						ret[j].emplace_back(i); 					} 				} 				return ret; 			} 		}; 

单元测试

int n; 		vector> edgeList; 		TEST_METHOD(TestMethod1) 		{ 			n = 2, edgeList = { {0,1} }; 			auto res = Solution().getAncestors(n, edgeList); 			AssertV2(vector>{ {}, {0}}, res); 		} 		TEST_METHOD(TestMethod2) 		{ 			n = 2, edgeList = { }; 			auto res = Solution().getAncestors(n, edgeList); 			AssertV2(vector>{ {}, {  }}, res); 		} 		TEST_METHOD(TestMethod15) 		{ 			n = 8, edgeList = { {0,3},{0,4},{1,3},{2,4},{2,7},{3,5},{3,6},{3,7},{4,6} }; 			auto res = Solution().getAncestors(n, edgeList); 			AssertV2(vector>{ {}, {}, {}, { 0,1 }, { 0,2 }, { 0,1,3 }, { 0,1,2,3,4 }, { 0,1,2,3 }}, res); 		} 		TEST_METHOD(TestMethod16) 		{ 			n = 5, edgeList = { {0,1},{0,2},{0,3},{0,4},{1,2},{1,3},{1,4},{2,3},{2,4},{3,4} }; 			auto res = Solution().getAncestors(n, edgeList); 			AssertV2(vector>{ {}, { 0 }, { 0,1 }, { 0,1,2 }, { 0,1,2,3 }}, res); 		} 		TEST_METHOD(TestMethod17) 		{ 			n = 8, edgeList ={ {0,7},{7,6},{0,3},{6,3},{5,4},{1,5},{2,7},{3,5},{3,1},{0,5},{7,5},{2,1},{1,4},{6,1} }; 			auto res = Solution().getAncestors(n, edgeList); 			AssertV2(vector>{ {}, { 0,2,3,6,7 }, {}, { 0,2,6,7 }, { 0,1,2,3,5,6,7 }, { 0,1,2,3,6,7 }, { 0,2,7 }, { 0,2 }}, res); 		} 

扩展阅读

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

视频课程

先学简单的课程,请移步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++**实现。

相关内容

热门资讯

透视代打(aapokER)aa... 透视代打(aapokER)aapoker猫腻(透视)确实存在有挂(详细辅助必赢教程)所有人都在同一条...
透视安装!德扑数据软件,(德州... 透视安装!德扑数据软件,(德州wpk)真是有挂(详细辅助2025新版技巧);透视安装!德扑数据软件,...
透视软件(aapoKer)aa... 透视软件(aapoKer)aapoker挂(透视)其实存在有挂(详细辅助曝光教程)1.aapoker...
透视肯定!德州ai辅助软件,(... 透视肯定!德州ai辅助软件,(德州nzt)都是真的是有挂(详细辅助我来教教你)1、这是跨平台的德州a...
透视代打!德州AI智能辅助机器... 透视代打!德州AI智能辅助机器人,(德州nzt)都是是有挂(详细辅助实用技巧)1、点击下载安装,德州...
透视代打(AApoker)aa... 透视代打(AApoker)aapoker有挂(透视)都是存在有挂(详细辅助专业教程)1、aapoke...
透视有挂(AAPOKER)aa... 透视有挂(AAPOKER)aapoker辅助工具存在(透视)其实是真的有挂(详细辅助大神讲解)1、每...
透视安装!德扑数据软件,(线上... 透视安装!德扑数据软件,(线上德州)一贯是有挂(详细辅助透牌教程)该软件可以轻松地帮助玩家将德扑数据...
透视辅助(德州aapoker俱... 透视辅助(德州aapoker俱乐部)aapoker俱乐部(透视)确实存在有挂(详细辅助2025新版教...
透视能赢!德州免费辅助神器ap... 透视能赢!德州免费辅助神器app,(线上wpk德州)一直有挂(详细辅助安装教程)1、玩家可以在德州免...