All Downloads are FREE. Search and download functionalities are using the official Maven repository.

g0801_0900.s0882_reachable_nodes_in_subdivided_graph.Solution Maven / Gradle / Ivy

There is a newer version: 1.38
Show newest version
package g0801_0900.s0882_reachable_nodes_in_subdivided_graph;

// #Hard #Heap_Priority_Queue #Graph #Shortest_Path
// #2022_03_28_Time_28_ms_(95.85%)_Space_66.3_MB_(87.56%)

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Queue;

/**
 * 882 - Reachable Nodes In Subdivided Graph\.
 *
 * Hard
 *
 * You are given an undirected graph (the **"original graph"** ) with `n` nodes labeled from `0` to `n - 1`. You decide to **subdivide** each edge in the graph into a chain of nodes, with the number of new nodes varying between each edge.
 *
 * The graph is given as a 2D array of `edges` where edges[i] = [ui, vi, cnti] indicates that there is an edge between nodes ui and vi in the original graph, and cnti is the total number of new nodes that you will **subdivide** the edge into. Note that cnti == 0 means you will not subdivide the edge.
 *
 * To **subdivide** the edge [ui, vi], replace it with (cnti + 1) new edges and cnti new nodes. The new nodes are x1, x2, ..., xcnti, and the new edges are [ui, x1], [x1, x2], [x2, x3], ..., [xcnti-1, xcnti], [xcnti, vi].
 *
 * In this **new graph** , you want to know how many nodes are **reachable** from the node `0`, where a node is **reachable** if the distance is `maxMoves` or less.
 *
 * Given the original graph and `maxMoves`, return _the number of nodes that are **reachable** from node_ `0` _in the new graph_.
 *
 * **Example 1:**
 *
 * ![](https://s3-lc-upload.s3.amazonaws.com/uploads/2018/08/01/origfinal.png)
 *
 * **Input:** edges = \[\[0,1,10],[0,2,1],[1,2,2]], maxMoves = 6, n = 3
 *
 * **Output:** 13
 *
 * **Explanation:** The edge subdivisions are shown in the image above. The nodes that are reachable are highlighted in yellow.
 *
 * **Example 2:**
 *
 * **Input:** edges = \[\[0,1,4],[1,2,6],[0,2,8],[1,3,1]], maxMoves = 10, n = 4
 *
 * **Output:** 23
 *
 * **Example 3:**
 *
 * **Input:** edges = \[\[1,2,4],[1,4,5],[1,3,1],[2,3,4],[3,4,5]], maxMoves = 17, n = 5
 *
 * **Output:** 1
 *
 * **Explanation:** Node 0 is disconnected from the rest of the graph, so only node 0 is reachable.
 *
 * **Constraints:**
 *
 * *   0 <= edges.length <= min(n * (n - 1) / 2, 104)
 * *   `edges[i].length == 3`
 * *   0 <= ui < vi < n
 * *   There are **no multiple edges** in the graph.
 * *   0 <= cnti <= 104
 * *   0 <= maxMoves <= 109
 * *   `1 <= n <= 3000`
**/
@SuppressWarnings("unchecked")
public class Solution {
    public int reachableNodes(int[][] edges, int maxMoves, int n) {
        // Build graph
        List[] graph = new List[n];
        for (int i = 0; i < n; ++i) {
            graph[i] = new ArrayList<>();
        }
        for (int[] edge : edges) {
            // how many nodes between u and v(inclusive)
            // vvvvvvvvvvvvvvv
            int u = edge[0];
            int v = edge[1];
            int w = edge[2] + 1;
            graph[u].add(new int[] {v, w});
            graph[v].add(new int[] {u, w});
        }
        // Do dijkstra
        Queue queue = new PriorityQueue<>((a, b) -> Integer.compare(a[1], b[1]));
        int[] dist = new int[n];
        Arrays.fill(dist, Integer.MAX_VALUE >> 1);
        dist[0] = 0;
        queue.add(new int[] {0, dist[0]});
        while (!queue.isEmpty()) {
            int[] curr = queue.poll();
            int u = curr[0];
            int d = curr[1];
            if (d != dist[u]) {
                continue;
            }
            for (int[] next : graph[u]) {
                int v = next[0];
                int w = next[1];
                if (dist[u] + w < dist[v]) {
                    dist[v] = dist[u] + w;
                    queue.add(new int[] {v, dist[v]});
                }
            }
        }
        // Count reachable nodes
        int ans = 0;
        for (int i = 0; i < n; i++) {
            if (dist[i] <= maxMoves) {
                ans++;
            }
        }
        for (int[] edge : edges) {
            int u = edge[0];
            int v = edge[1];
            int w = edge[2];
            // Nodes can be extended from (u, v) in at most maxMoves steps
            // if maxMoves - dist[u] < 0, then l = 0
            int l = Math.max(0, maxMoves - dist[u]);
            int r = Math.max(0, maxMoves - dist[v]);
            // l + r shouldn't be greater than w
            ans += Math.min(w, l + r);
        }
        return ans;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy