给你一个整数 n ,它表示一个 带权有向 图的节点数,节点编号为 0 到 n - 1 。

    同时给你一个二维整数数组 edges ,其中 edges[i] = [fromi, toi, weighti] ,表示从 fromi 到 toi 有一条边权为 weighti 的 有向 边。

    最后,给你三个 互不相同 的整数 src1 ,src2 和 dest ,表示图中三个不同的点。

    请你从图中选出一个 边权和最小 的子图,使得从 src1 和 src2 出发,在这个子图中,都 可以 到达 dest 。如果这样的子图不存在,请返回 -1 。

    子图 中的点和边都应该属于原图的一部分。子图的边权和定义为它所包含的所有边的权值之和。

    示例 1:

    image.png

    输入: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 <= 105
    0 <= edges.length <= 105
    edges[i].length == 3
    0 <= fromi, toi, src1, src2, dest <= n - 1
    fromi != toi
    src1 ,src2 和 dest 两两不同。
    1 <= weight[i] <= 105


    1. class Solution {
    2. //建立正反图,然后求src1, src2, dest到达的每个点的最短路径,枚举每个点如果能到达三个点,就更新答案
    3. static int inf = -1;
    4. public long minimumWeight(int n, int[][] edges, int src1, int src2, int dest) {
    5. //rh反向图, h正向图
    6. List<int[]>[] h = create(edges, n, true);
    7. List<int[]>[] rh = create(edges, n, false);
    8. //三个点的最短路
    9. long[] dist1 = dijkstra(src1, n, h);
    10. long[] dist2 = dijkstra(src2, n, h);
    11. long[] dist3 = dijkstra(dest, n, rh);
    12. long res = Long.MAX_VALUE;
    13. for (int i = 0; i < n; ++i) {
    14. if (dist1[i] != inf && dist2[i] != inf && dist3[i] != inf)
    15. res = Math.min(res, dist1[i] + dist2[i] + dist3[i]);
    16. }
    17. if (res == Long.MAX_VALUE) return -1;
    18. return res;
    19. }
    20. //建图,邻接矩阵
    21. private List<int[]>[] create(int[][] edges, int n, boolean sign) {
    22. List<int[]>[] h = new List[n];
    23. for (int i = 0; i < n; ++i)
    24. h[i] = new ArrayList<int[]>();
    25. for (int[] t : edges) {
    26. //正向图
    27. if (sign) h[t[0]].add(new int[]{t[1], t[2]});
    28. else h[t[1]].add(new int[]{t[0], t[2]});
    29. }
    30. return h;
    31. }
    32. private long[] dijkstra(int start, int n, List<int[]>[] h) {
    33. long[] dist = new long[n];
    34. Arrays.fill(dist, inf);
    35. boolean[] vis = new boolean[n];
    36. //堆优化
    37. PriorityQueue<long[]> q = new PriorityQueue<>((a, b) -> Long.compare(a[1], b[1]));
    38. dist[start] = 0;
    39. q.add(new long[]{start, 0});
    40. while (!q.isEmpty()) {
    41. long[] t = q.poll();
    42. if (vis[(int)t[0]]) continue;
    43. vis[(int)t[0]] = true;
    44. for (int[] next : h[(int)t[0]]) {
    45. if (dist[next[0]] == inf || dist[next[0]] > t[1] + next[1]) {
    46. dist[next[0]] = t[1] + next[1];
    47. q.add(new long[]{next[0], dist[next[0]]});
    48. }
    49. }
    50. }
    51. return dist;
    52. }
    53. }