2023-10-04:用 go 语言,现有一棵无向、无根的树,树中有 n 个节点,按从 0 到 n - 1 编号 给你一个整数 n 和一个长度为 n - 1 的二维整数数组 edges , 其中 edge
2023-10-04:用 go 语言,现有一棵无向、无根的树,树中有 n 个节点,按从 0 到 n - 1 编号
给你一个整数 n 和一个长度为 n - 1 的二维整数数组 edges ,
其中 edges[i] = [ai, bi] 表示树中节点 ai 和 bi 之间存在一条边。
每个节点都关联一个价格。给你一个整数数组 price ,其中 price[i] 是第 i 个节点的价格。
给定路径的 价格总和 是该路径上所有节点的价格之和。
另给你一个二维整数数组 trips ,其中 trips[i] = [starti, endi] 表示
从节点 starti 开始第 i 次旅行,并通过任何你喜欢的路径前往节点 endi 。
在执行第一次旅行之前,你可以选择一些 非相邻节点 并将价格减半。
返回执行所有旅行的最小价格总和。
输入:n = 4, edges = [[0,1],[1,2],[1,3]], price = [2,2,10,6], trips = [[0,3],[2,1],[2,3]]。
输出:23。
来自左程云。
答案 2023-10-04:
大体过程如下:
1.构建图:根据输入的 edges 构建无向图,使用邻接表存储每个节点的邻居节点。
2.初始化查询数组:根据 trips 初始化查询数组,将每个旅行的起点和终点加入到对应节点的查询数组中。
3.初始化并查集:初始化一个并查集,用于保存节点的父节点信息和标签。将每个节点的父节点初始化为自身,标签初始化为-1。
4.进行 Tarjan 算法:从根节点开始遍历树,使用递归的方式进行深度优先搜索。
对于每个节点 cur,记录其父节点 father。
遍历 cur 的邻居节点 next,如果 next 不等于 father,进行递归操作。
递归操作结束后,将 cur 和 next 节点合并,设置它们的标签为 cur。
对于 cur 节点的查询数组中的每个查询,如果查询的终点的标签不为-1,说明该查询经过 cur 节点,记录查询的终点标签为最低公共祖先节点。
5.计算每个节点的旅行个数:遍历旅行数组,统计每个节点作为起点或终点的旅行个数。
对于每个旅行,起点和终点的旅行个数加 1,最低公共祖先节点的旅行个数减 1。
如果最低公共祖先节点的父节点不为-1,最低公共祖先节点的父节点的旅行个数减 1。
6.使用深度优先搜索计算价格总和:从根节点开始,使用递归的方式进行深度优先搜索。
对于每个节点 cur,计算不选择减半价格的情况下的总价格 no 和选择减半价格的情况下的总价格
遍历 cur 的邻居节点 next,如果 next 不等于 father,进行递归操作。
更新 no 和 yes 的值。
7.返回最小价格总和:取 no 和 yes 中较小的值作为最小价格总和。
总的时间复杂度:O(n)(遍历节点和邻居节点) + O(m)(遍历查询数组) + O(n)(遍历旅行数组) + O(n)(遍历节点和邻居节点) = O(n + m)
总的额外空间复杂度:O(n)(存储图) + O(m)(存储查询数组) + O(n)(存储父节点信息) + O(n)(存储旅行个数) + O(n)(存储价格总和) = O(n + m)
go 完整代码如下:
版权声明: 本文为 InfoQ 作者【福大大架构师每日一题】的原创文章。
原文链接:【http://xie.infoq.cn/article/69fc7a6e041fd29b1d453218f】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论