azarasi / LeetCode 6032. Minimum Weighted Subgraph With the Required Paths

Created Sun, 13 Mar 2022 20:28:53 +0800 Modified Wed, 18 Sep 2024 14:00:22 +0000

You are given an integer n denoting the number of nodes of a weighted directed graph. The nodes are numbered from 0 to n - 1.

You are also given a 2D integer array edges where \(edges[i] = [from_i, to_i, weight_i]\) denotes that there exists a directed edge from \(from_i\) to \(to_i\) with weight \(weight_i\).

Lastly, you are given three distinct integers src1, src2, and dest denoting three distinct nodes of the graph.

Return the minimum weight of a subgraph of the graph such that it is possible to reach dest from both src1 and src2 via a set of edges of this subgraph. In case such a subgraph does not exist, return -1.

A subgraph is a graph whose vertices and edges are subsets of the original graph. The weight of a subgraph is the sum of weights of its constituent edges.

Example 1:

Input: 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

Output: 9

Explanation: The above figure represents the input graph. The blue edges represent one of the subgraphs that yield the optimal answer. Note that the subgraph [[1,0,3],[0,5,6]] also yields the optimal answer. It is not possible to get a subgraph with less weight satisfying all the constraints.

Example 2:

Input: n = 3, edges = [[0,1,1],[2,1,1]], src1 = 0, src2 = 1, dest = 2

Output: -1

Explanation: The above figure represents the input graph. It can be seen that there does not exist any path from node 1 to node 2, hence there are no subgraphs satisfying all the constraints.

Constraints:

  • \(3 <= n <= 10^5\)
  • \(0 <= edges.length <= 10^5\)
  • edges[i].length == 3
  • 0 <= fromi, toi, src1, src2, dest <= n - 1
  • \(from_i != to_i\)
  • src1, src2, and dest are pairwise distinct.
  • \(1 <= weight[i] <= 10^5\)
  • Consider what the paths from src1 to dest and src2 to dest would look like in the optimal solution.
  • It can be shown that in an optimal solution, the two paths from src1 and src2 will coincide at one node, and the remaining part to dest will be the same for both paths. Now consider how to find the node where the paths will coincide.
  • How can algorithms for finding the shortest path between two nodes help us?

Solution

从 src1​ 和 src2​ 都可以到达 dest 的子图,一定是先从 src1​→mid,src2​→mid,然后再一起从 mid 出发,到达 dest 的形式,如下图:

image.png

证明:若路径 src1​→dest 与 src2​→dest 的 第一个交点 是 mid,那么一起从 mid 走到 dest 是最优的,因为如果不一起走,那么从 mid 到 dest 就存在多条路径,此时只需选择一条最短的路径一起走,代价一定小于多条路径的权值和。

解法:

枚举中间节点 mid=i,利用 dijkstra 算法,计算

dist_src1[i]= 从 src1​ 出发,到达节点 i 的距离;

dist_src2[i]= 从 src2​ 出发,到达节点 i 的距离;

dist_dest[i]= 从 dest 出发,沿着 反向边,到达节点 i 的距离。

那么,答案就是 \(\displaystyle{\min_{0\le i \le n-1}(dist\_src1[i] + dist\_src2[i] + dist\_dest[i])}\)。

class Solution {
public:
    void calc_dist(int s, vector<pair<int, int>> *graph, vector<long long int> &dist) {
        priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<>> pq;
        dist[s] = 0;
        pq.emplace(0, s);
        while(!pq.empty()) {
            auto [weight, node] = pq.top();
            pq.pop();
            if(weight > dist[node]) {
                continue;
            }
            for(auto [next_node, next_weight]: graph[node]) {
                if(weight + next_weight < dist[next_node]) {
                    dist[next_node] = weight + next_weight;
                    pq.emplace(weight + next_weight, next_node);
                }
            }
        }
    }

    long long minimumWeight(int n, vector<vector<int>>& edges, int src1, int src2, int dest) {
        vector<pair<int, int>> graph[n], graph_rev[n];
        for(auto &edge: edges) {
            auto from   = edge[0];
            auto to     = edge[1];
            auto weight = edge[2];
            graph[from].emplace_back(to, weight);
            graph_rev[to].emplace_back(from, weight);
        }

        long long a = LONG_LONG_MAX;
        vector<long long> dist_src1(n, LONG_LONG_MAX), dist_src2(n, LONG_LONG_MAX), dist_dest(n, LONG_LONG_MAX);

        calc_dist(src1, graph, dist_src1);
        calc_dist(src2, graph, dist_src2);
        calc_dist(dest, graph_rev, dist_dest);

        long long ans = LONG_LONG_MAX;

        for(int i = 0; i < n; ++i) {
            if(dist_src1[i] != LONG_LONG_MAX && dist_src2[i] != LONG_LONG_MAX && dist_dest[i] != LONG_LONG_MAX) {
                ans = min(ans, dist_src1[i] + dist_src2[i] + dist_dest[i]);
            }
        }
        if(ans == LONG_LONG_MAX) {
            ans = -1;
        }
        return ans;
    }
};