2203. 包含要求路径的最小带权子图
题目描述
给你一个整数 n ,它表示一个 带权有向 图的节点数,节点编号为 0 到 n - 1 。
同时给你一个二维整数数组 edges ,其中 edges[i] = [fromi, toi, weighti] ,表示从 fromi 到 toi 有一条边权为 weighti 的 有向 边。
最后,给你三个 互不相同 的整数 src1 ,src2 和 dest ,表示图中三个不同的点。
请你从图中选出一个 边权和最小 的子图,使得从 src1 和 src2 出发,在这个子图中,都 可以 到达 dest 。如果这样的子图不存在,请返回 -1 。
子图 中的点和边都应该属于原图的一部分。子图的边权和定义为它所包含的所有边的权值之和。
示例 1:
输入:n = 6, edges = [[0,2,2],[0,5,6],[1,0,3],[1,4,5],[2,1,1],[2,3,3],[2,3,4],[3,4,2],[4,5,1]], src1 = 0, src2 = 1, dest = 5 输出:9 解释: 上图为输入的图。 蓝色边为最优子图之一。 注意,子图 [[1,0,3],[0,5,6]] 也能得到最优解,但无法在满足所有限制的前提下,得到更优解。
示例 2:
输入:n = 3, edges = [[0,1,1],[2,1,1]], src1 = 0, src2 = 1, dest = 2 输出:-1 解释: 上图为输入的图。 可以看到,不存在从节点 1 到节点 2 的路径,所以不存在任何子图满足所有限制。
提示:
3 <= n <= 1050 <= edges.length <= 105edges[i].length == 30 <= fromi, toi, src1, src2, dest <= n - 1fromi != toisrc1,src2和dest两两不同。1 <= weight[i] <= 105
解法
方法一:枚举三条最短路的交汇点
思考
需要一张同时包含 \(src_1 \to dest\) 与 \(src_2 \to dest\) 的子图,且权和最小。分别取两条最短路再并起来,会在交汇之前重复计权,也不保证全局最优。\(n, m \le 10^5\),不能枚举子图。
两条路径最终都到达 \(dest\),因此必有某个交汇点 \(p\)(可以就是 \(dest\))。最优子图由三条最短路拼成:\(src_1 \to p\)、\(src_2 \to p\) 以及 \(p \to dest\)。
为此在原图上从 \(src_1\)、\(src_2\) 各跑一次 Dijkstra,再把边反向后从 \(dest\) 跑一次,得到 \(d_1\)、\(d_2\)、\(d_3\)。枚举每个点作为 \(p\),取 \(d_1[p]+d_2[p]+d_3[p]\) 的最小值;若仍为无穷则不存在。
最短路问题。
我们假设从 \(src1\) 出发到 \(dest\) 的一条最短路径为 \(A\),从 \(src2\) 出发到 \(dest\) 的一条最短路径为 \(B\)。
\(A\), \(B\) 两条路径一定存在着公共点 \(p\),因为 \(dest\) 一定是其中一个公共点。那么问题可以转换为求以下三条路径和的最小值:
- 从 \(src1\) 到 \(p\) 的最短路
- 从 \(src2\) 到 \(p\) 的最短路
- 从 \(p\) 到 \(dest\) 的最短路(这里我们可以将原图的所有边反向,然后转换为从 \(dest\) 到 \(p\) 的最短路)
我们进行三次 Dijkstra 算法,就可以求出 \(src1\), \(src2\), \(dest\) 到其他点的最短路径。
公共点可以有多个,因此我们在 \([0,n)\) 范围内枚举公共点 \(p\),找出边权之和最小的值即可。
时间复杂度 \(O(mlogn)\),其中 m 表示数组 \(edges\) 的长度。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | |

