Minimum Time Required to Visit Each Disappearing Nodes

Last Updated : 23 Jul, 2025

Given an undirected graph with n nodes that are represented by a 2D array edges where edges[i] = [ui, vi, timei] describes an edge between nodes ui and vi with a traversal time of timei. Additionally, you are given an array disappear[], where disappear[i] denotes the time when node i becomes unavailable. The graph may be disconnected and contain multiple edges. The task is to return an array answer[] where answer[i] represents the minimum time required to reach node i from node 0. If node i is unreachable from node 0, answer[i] should be -1.

Example:

Input: n = 3, edges = [[0,1,2],[1,2,1],[0,2,4]], disappear = [1,1,5]
Output: [0,-1,4]
Explanation: We are starting our journey from node 0, and our goal is to find the minimum time required to reach each node before it disappears.

  • For node 0, we don't need any time as it is our starting point.
  • For node 1, we need at least 2 units of time to traverse edges[0]. Unfortunately, it disappears at that moment, so we won't be able to visit it.
  • For node 2, we need at least 4 units of time to traverse edges[2].

Input: n = 3, edges = [[0,1,2],[1,2,1],[0,2,4]], disappear = [1,3,5]
Output: [0,2,3]
Explanation: We are starting our journey from node 0, and our goal is to find the minimum time required to reach each node before it disappears.

  • For node 0, we don't need any time as it is the starting point.
  • For node 1, we need at least 2 units of time to traverse edges[0].
  • For node 2, we need at least 3 units of time to traverse edges[0] and edges[1].

Approach:

We can use Dijkstra's algorithm, which is specifically designed for finding the shortest paths in graphs with non-negative weights. Here's the plan:

We'll represent the graph using an adjacency list, where each node points to its neighbors along with the travel time between them. Dijkstra's algorithm uses a priority queue (min-heap) to ensure we always expand the node with the smallest known distance first, which guarantees that we explore the shortest path first. We'll maintain an array to store the shortest distances to each node, initializing all distances to infinity (except for the source node, which starts at 0). As we process each node, we'll update the distances to its neighboring nodes only if the new distance is shorter and within the time limit before the neighbor disappears. If a node cannot be reached before it disappears, it won't be considered further. After processing all nodes, any node that remains with a distance of infinity means it's unreachable, and we'll set its distance to -1. This way, we ensure to maintain both the shortest paths and the disappearance constraints. Finally, we'll return the array of minimum times required to reach each node.

Steps-by-step approach:

  • Build an adjacency list from the given edges where each node points to its neighbors and the respective traversal times.
  • Use a priority queue (min-heap) to manage nodes by their current known shortest distance.
  • Initialize a distance[] array with all values set to infinity (INT_MAX), except for the source node (node 0), which is set to 0.
  • While the priority queue is not empty:
    • Extract the node with the smallest known distance.
    • For each neighboring node, calculate the potential new distance.
      • If this new distance is shorter than the current known distance and is less than the disappearance time of the neighboring node
        • Update the distance and add the neighbor to the priority queue.
  • Convert all distances that remain infinity (INT_MAX) to -1, indicating those nodes are unreachable from the source node.
  • Return the distance array containing the minimum time required to reach each node from node 0.

Below is the implementation of the above approach:

C++
#include <bits/stdc++.h>
using namespace std;

vector<int> minimumTime(int n, vector<vector<int> >& edges,
                        vector<int>& disappear)
{
    // Step 1: Build the adjacency list
    vector<vector<pair<int, int> > > adj(n);
    for (const auto& edge : edges) {
        adj[edge[0]].emplace_back(edge[1], edge[2]);
        adj[edge[1]].emplace_back(edge[0], edge[2]);
    }

    // Step 2: Priority queue for Dijkstra's algorithm
    priority_queue<pair<int, int>, vector<pair<int, int> >,
                   greater<pair<int, int> > >
        minHeap;

    // Step 3: Distance array initialization
    vector<int> dist(n, INT_MAX);
    dist[0] = 0;
    minHeap.push({ 0, 0 }); // (distance, node)

    // Step 4: Dijkstra's algorithm with the disappearance
    // constraint
    while (!minHeap.empty()) {
        auto curr = minHeap.top();
        minHeap.pop();

        int currDist = curr.first;
        int currNode = curr.second;

        if (currDist > dist[currNode])
            continue;

        for (const auto neighbour : adj[currNode]) {
            int childNode = neighbour.first;
            int childDist = neighbour.second;

            if (currDist + childDist < dist[childNode]
                && currDist + childDist
                       < disappear[childNode]) {
                dist[childNode] = currDist + childDist;
                minHeap.push(
                    { dist[childNode], childNode });
            }
        }
    }

    // Step 5: Replace INT_MAX with -1 for unreachable nodes
    for (int i = 0; i < n; ++i) {
        if (dist[i] == INT_MAX) {
            dist[i] = -1;
        }
    }

    return dist;
}

// Driver code
int main()
{

    int n = 3;
    vector<vector<int> > edges
        = { { 0, 1, 2 }, { 1, 2, 1 }, { 0, 2, 4 } };
    vector<int> disappear = { 1, 1, 5 };

    vector<int> result = minimumTime(n, edges, disappear);
    for (int time : result) {
        cout << time << " ";
    }
    cout << endl;

    return 0;
}
Java
import java.util.*;

public class MinimumTimeFinder {

    public static List<Integer>
    minimumTime(int n, List<List<Integer> > edges,
                List<Integer> disappear)
    {
        // Step 1: Build the adjacency list
        List<List<int[]> > adj = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            adj.add(new ArrayList<>());
        }
        for (List<Integer> edge : edges) {
            int u = edge.get(0);
            int v = edge.get(1);
            int weight = edge.get(2);
            adj.get(u).add(new int[] { v, weight });
            adj.get(v).add(new int[] { u, weight });
        }

        // Step 2: Priority queue for Dijkstra's algorithm
        PriorityQueue<int[]> minHeap = new PriorityQueue<>(
            Comparator.comparingInt(a -> a[0]));

        // Step 3: Distance array initialization
        int[] dist = new int[n];
        Arrays.fill(dist, Integer.MAX_VALUE);
        dist[0] = 0;
        minHeap.offer(
            new int[] { 0, 0 }); // (distance, node)

        // Step 4: Dijkstra's algorithm with the
        // disappearance constraint
        while (!minHeap.isEmpty()) {
            int[] curr = minHeap.poll();
            int currDist = curr[0];
            int currNode = curr[1];

            if (currDist > dist[currNode])
                continue;

            for (int[] neighbour : adj.get(currNode)) {
                int childNode = neighbour[0];
                int childDist = neighbour[1];

                if (currDist + childDist < dist[childNode]
                    && currDist + childDist
                           < disappear.get(childNode)) {
                    dist[childNode] = currDist + childDist;
                    minHeap.offer(new int[] {
                        dist[childNode], childNode });
                }
            }
        }

        // Step 5: Replace Integer.MAX_VALUE with -1 for
        // unreachable nodes
        List<Integer> result = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            if (dist[i] == Integer.MAX_VALUE) {
                result.add(-1);
            }
            else {
                result.add(dist[i]);
            }
        }

        return result;
    }

    public static void main(String[] args)
    {
        int n = 3;
        List<List<Integer> > edges = Arrays.asList(
            Arrays.asList(0, 1, 2), Arrays.asList(1, 2, 1),
            Arrays.asList(0, 2, 4));
        List<Integer> disappear = Arrays.asList(1, 1, 5);

        List<Integer> result
            = minimumTime(n, edges, disappear);
        for (int time : result) {
            System.out.print(time + " ");
        }
        System.out.println();
    }
}

// This code is contributed by Shivam Gupta

Output
0 -1 4 

Time Complexity: O(V logV + E), where V is the number of vertices and E is the number of edges.
Auxiliary Space: O(V+E), where V is the number of vertices and E is the number of edges.

Comment