Given an undirected tree having N nodes numbered from 0 to N – 1. Additionally, a 2D integer array, edges[][] of length N – 1, is provided, where edges[i]=[u, v, w] indicates an undirected edge between nodes u and v with a weight w.
The task is to return an answer array of length N, where answer[i] represents the minimum time required for i’th node to reach any leaf node.
Note: The total time taken to reach from one node to another is the sum of all the edge weight in the path.
Examples:
Input: N = 3, edges[][]={{0, 1, 5}, {1, 2, 3}} Output: {0,3,0} Explanation: Nodes 0 and 2 are identified as magical nodes due to their single edge connection (degree is 1). Consequently, the minimum time required to reach a magical node from both 0 and 2 is 0. Now, considering node 1, the minimum time to reach a magical node is determined as min(5, 3), resulting in 3.
Input: N = 5, edges[][] = {{0, 1, 6}, {1, 4, 10}, {0, 2, 4}, {2, 3, 8}} Output: {12,10,8,0,0} Explanation: In this scenario, nodes 3 and 4, with a degree of 1 (as connected with 1 edge), are designated as magical nodes. For node 2, the minimum time required to reach node 3 is 8, and the time required to reach node 4 is 20. Therefore, the answer for the 2nd node is 8. Similarly, for nodes 0 and 1, the respective answers are 12 and 10.
Approach: To solve the problem, follow the below idea:
The main idea is to use Dijkstra’s algorithm to efficiently find the minimum time to reach leaf node from each node in the tree. We start a multi-source Dijkstra’s algorithm where all the leaves are considered as source nodes. Now, running Dijkstra’s Algorithm will get us the minimum distance of all the nodes from any leaf node. Since, the graph is undirected the minimum distance from leaf nodes to a node is same as the minimum distance from that node to the leaf nodes.
Step-by-step algorithm:
- Create an adjacency list graph[][] to represent the tree structure, where each node is connected to its neighboring nodes with their respective travel times.
- Initialize a distance array distance[] to store the minimum time required to reach a leaf node from each node. Initialize all distances to infinity (LLONG_MAX).
- Create a priority queue pq to store nodes with their corresponding distances.
- Initially, add all leaf nodes to the priority queue with a distance of 0.
- Use Dijkstra’s algorithm to process nodes from the priority queue.
- For each node, update the distance to its neighboring nodes if a shorter path is found.
- Continue processing nodes until the priority queue is empty.
- Return the distance array, which contains the minimum time to reach a magical node from each node.
Below is the implementation of the code:
C++
#include <bits/stdc++.h>
#include <iostream>
using namespace std;
vector< long long > disTree( int n,
vector<vector< int > >& edges)
{
vector<vector<pair< long long , long long > > > graph(n);
for ( int i = 0; i < edges.size(); ++i) {
long long x = edges[i][0];
long long y = edges[i][1];
long long w = edges[i][2];
graph[x].emplace_back(y, w);
graph[y].emplace_back(x, w);
}
vector< long long > distance(n, LLONG_MAX);
priority_queue<pair< long long , long long >,
vector<pair< long long , long long > >,
greater<pair< long long , long long > > >
pq;
for ( int i = 0; i < n; ++i) {
if (graph[i].size() == 1) {
pq.push({ 0, i });
}
}
while (!pq.empty()) {
auto temp = pq.top();
pq.pop();
long long dist = temp.first;
long long node = temp.second;
if (distance[node] <= dist) {
continue ;
}
distance[node] = dist;
for ( const auto & e : graph[node]) {
long long v = e.first;
long long t = e.second;
if (distance[v] > dist + t) {
pq.push({ dist + t, v });
}
}
}
return distance;
}
int main()
{
int n = 3;
vector<vector< int > > edges
= { { 0, 1, 5 }, { 1, 2, 3 } };
vector< long long > ans = disTree(n, edges);
for ( auto a : ans) {
cout << a << " " ;
}
return 0;
}
|
Java
import java.util.*;
public class Main {
static List<Long> disTree( int n,
List<List<Integer> > edges)
{
List<List<Pair> > graph = new ArrayList<>(n);
for ( int i = 0 ; i < n; ++i) {
graph.add( new ArrayList<>());
}
for ( int i = 0 ; i < edges.size(); ++i) {
int x = edges.get(i).get( 0 );
int y = edges.get(i).get( 1 );
int w = edges.get(i).get( 2 );
graph.get(x).add( new Pair(y, w));
graph.get(y).add( new Pair(x, w));
}
List<Long> distance = new ArrayList<>(
Collections.nCopies(n, Long.MAX_VALUE));
PriorityQueue<Pair> pq = new PriorityQueue<>(
Comparator.comparingLong(Pair::getFirst));
for ( int i = 0 ; i < n; ++i) {
if (graph.get(i).size() == 1 ) {
pq.add( new Pair( 0 , i));
}
}
while (!pq.isEmpty()) {
Pair temp = pq.poll();
long dist = temp.getFirst();
int node = temp.getSecond();
if (distance.get(node) <= dist) {
continue ;
}
distance.set(node, dist);
for (Pair e : graph.get(node)) {
int v = ( int )e.getFirst();
long t = e.getSecond();
if (distance.get(v) > dist + t) {
pq.add( new Pair(dist + t, v));
}
}
}
return distance;
}
public static void main(String[] args)
{
int n = 3 ;
List<List<Integer> > edges
= List.of(List.of( 0 , 1 , 5 ), List.of( 1 , 2 , 3 ));
List<Long> ans = disTree(n, edges);
for ( long a : ans) {
System.out.print(a + " " );
}
}
static class Pair {
private final long first;
private final int second;
public Pair( long first, int second)
{
this .first = first;
this .second = second;
}
public long getFirst() { return first; }
public int getSecond() { return second; }
}
}
|
C#
using System;
using System.Collections.Generic;
class Program
{
static List< long > DisTree( int n, List<List< int >> edges)
{
List<List<Tuple< long , long >>> graph = new List<List<Tuple< long , long >>>(n);
for ( int i = 0; i < n; i++)
{
graph.Add( new List<Tuple< long , long >>());
}
foreach (List< int > edge in edges)
{
long x = edge[0];
long y = edge[1];
long w = edge[2];
graph[( int )x].Add( new Tuple< long , long >(y, w));
graph[( int )y].Add( new Tuple< long , long >(x, w));
}
List< long > distance = new List< long >();
for ( int i = 0; i < n; i++)
{
distance.Add( long .MaxValue);
}
PriorityQueue<Tuple< long , long >> pq = new PriorityQueue<Tuple< long , long >>(
(x, y) => x.Item1.CompareTo(y.Item1)
);
for ( int i = 0; i < n; ++i)
{
if (graph[i].Count == 1)
{
pq.Enqueue( new Tuple< long , long >(0, i));
}
}
while (!pq.IsEmpty())
{
Tuple< long , long > temp = pq.Dequeue();
long dist = temp.Item1;
long node = temp.Item2;
if (distance[( int )node] <= dist)
{
continue ;
}
distance[( int )node] = dist;
foreach (Tuple< long , long > e in graph[( int )node])
{
long v = e.Item1;
long t = e.Item2;
if (distance[( int )v] > dist + t)
{
pq.Enqueue( new Tuple< long , long >(dist + t, v));
}
}
}
return distance;
}
static void Main( string [] args)
{
int n = 3;
List<List< int >> edges = new List<List< int >>()
{
new List< int >() { 0, 1, 5 },
new List< int >() { 1, 2, 3 }
};
List< long > ans = DisTree(n, edges);
foreach ( long a in ans)
{
Console.Write(a + " " );
}
}
}
public class PriorityQueue<T>
{
private List<T> data;
private Comparison<T> comparison;
public PriorityQueue(Comparison<T> comparison)
{
data = new List<T>();
this .comparison = comparison;
}
public void Enqueue(T item)
{
data.Add(item);
int ci = data.Count - 1;
while (ci > 0)
{
int pi = (ci - 1) / 2;
if (comparison(data[ci], data[pi]) >= 0) break ;
T tmp = data[ci]; data[ci] = data[pi]; data[pi] = tmp;
ci = pi;
}
}
public T Dequeue()
{
int li = data.Count - 1;
T frontItem = data[0];
data[0] = data[li];
data.RemoveAt(li);
--li;
int pi = 0;
while ( true )
{
int ci = pi * 2 + 1;
if (ci > li) break ;
int rc = ci + 1;
if (rc <= li && comparison(data[rc], data[ci]) < 0)
ci = rc;
if (comparison(data[pi], data[ci]) <= 0) break ;
T tmp = data[pi]; data[pi] = data[ci]; data[ci] = tmp;
pi = ci;
}
return frontItem;
}
public T Peek()
{
T frontItem = data[0];
return frontItem;
}
public int Count
{
get { return data.Count; }
}
public bool IsEmpty()
{
return data.Count == 0;
}
}
|
Javascript
class PriorityQueue {
constructor(comparator) {
this .heap = [];
this .comparator = comparator;
}
add(value) {
this .heap.push(value);
this .bubbleUp();
}
poll() {
const top = this .heap[0];
const bottom = this .heap.pop();
if ( this .heap.length > 0) {
this .heap[0] = bottom;
this .bubbleDown();
}
return top;
}
bubbleUp() {
let index = this .heap.length - 1;
while (index > 0) {
const current = this .heap[index];
const parentIndex = Math.floor((index - 1) / 2);
const parent = this .heap[parentIndex];
if ( this .comparator(current, parent) >= 0) break ;
this .heap[index] = parent;
this .heap[parentIndex] = current;
index = parentIndex;
}
}
bubbleDown() {
let index = 0;
const length = this .heap.length;
const current = this .heap[0];
while ( true ) {
let leftChildIndex = 2 * index + 1;
let rightChildIndex = 2 * index + 2;
let leftChild, rightChild;
let swap = null ;
if (leftChildIndex < length) {
leftChild = this .heap[leftChildIndex];
if ( this .comparator(leftChild, current) < 0) {
swap = leftChildIndex;
}
}
if (rightChildIndex < length) {
rightChild = this .heap[rightChildIndex];
if ((swap === null && this .comparator(rightChild, current) < 0) ||
(swap !== null && this .comparator(rightChild, leftChild) < 0)) {
swap = rightChildIndex;
}
}
if (swap === null ) break ;
this .heap[index] = this .heap[swap];
this .heap[swap] = current;
index = swap;
}
}
peek() {
return this .heap[0];
}
size() {
return this .heap.length;
}
}
function disTree(n, edges) {
const graph = new Array(n).fill( null ).map(() => []);
for (const edge of edges) {
const [x, y, w] = edge;
graph[x].push([y, w]);
graph[y].push([x, w]);
}
const distance = Array(n).fill(Number.MAX_SAFE_INTEGER);
const pq = new PriorityQueue(([distA], [distB]) => distA - distB);
for (let i = 0; i < n; i++) {
if (graph[i].length === 1) {
pq.add([0, i]);
}
}
while (pq.size() > 0) {
const [dist, node] = pq.poll();
if (distance[node] <= dist) continue ;
distance[node] = dist;
for (const [v, t] of graph[node]) {
if (distance[v] > dist + t) {
pq.add([dist + t, v]);
}
}
}
return distance;
}
function main() {
const n = 3;
const edges = [[0, 1, 5], [1, 2, 3]];
const ans = disTree(n, edges);
console.log( "Distances:" , ans.join( " " ));
}
main();
|
Python3
import heapq
def disTree(n, edges):
graph = [[] for _ in range (n)]
for edge in edges:
x, y, w = edge
graph[x].append((y, w))
graph[y].append((x, w))
distance = [ float ( 'inf' )] * n
pq = [( 0 , i) for i in range (n) if len (graph[i]) = = 1 ]
while pq:
dist, node = heapq.heappop(pq)
if distance[node] < = dist:
continue
distance[node] = dist
for v, t in graph[node]:
if distance[v] > dist + t:
heapq.heappush(pq, (dist + t, v))
return distance
def main():
n = 3
edges = [( 0 , 1 , 5 ), ( 1 , 2 , 3 )]
ans = disTree(n, edges)
for a in ans:
print (a, end = " " )
if __name__ = = "__main__" :
main()
|
Time Complexity: O(N * log(N)), where N is the number of nodes in the graph. Auxiliary Space: O(N)
|