Given a connected, undirected graph with V vertices numbered from 0 to V - 1 and an array edges[][], where each edge is represented as [u, v, t] indicating that there is an edge between vertices u and v with a travel time of t, determine the minimum time required for a message sent from vertex 0 to reach every vertex in the graph.
When a vertex receives the message, it immediately forwards it to all of its neighboring vertices. Return the minimum time required for the message to reach every vertex in the network.
Examples:
Input: V = 4, edges[][] = [[0, 1, 2], [1, 2, 1], [2, 3, 3]]
Output: 6
Explanation: The message starts at node 0.
Node 1 receives the message after 2 units of time.
Node 2 receives the message after 2 + 1 = 3 units of time.
Node 3 receives the message after 3 + 3 = 6 units of time.
Since node 3 is the last node to receive the message, the total time required for all nodes to receive the message is 6.Input: V = 4, edges[][] = [[0, 1, 2], [0, 2, 3], [0, 3, 1]]
Output: 3
Explanation: The message starts at node 0 and is sent to all of its neighboring nodes simultaneously.
Node 3 receives the message after 1 unit of time.
Node 1 receives the message after 2 units of time.
Node 2 receives the message after 3 units of time.
Since node 2 receives the message last, the total time required for all nodes to receive the message is 3.
Table of Content
[Naive Approach] Relax All Edges Repeatedly - O(V * E) Time and O(V) Space
The idea is to compute the minimum time required to reach every vertex by repeatedly relaxing all the edges. Initially, only vertex 0 is reachable with a time of 0, while all other vertices are considered unreachable. By updating the minimum time through every edge multiple times, the shortest travel time to each vertex is eventually obtained. The maximum among these times gives the minimum time required for the message to reach every vertex.
Working of Approach:
- Initialize the time to reach every vertex as infinity, except vertex 0, whose time is 0.
- Repeat V - 1 times and traverse all the edges.
- For each edge, update the minimum time of both endpoints if a shorter path is found through the other endpoint.
- After all relaxations, the minimum time to reach every vertex is obtained.
- Return the maximum value among all the computed times.
#include <iostream>
#include <vector>
#include <climits>
#include <algorithm>
using namespace std;
int distributedSystems(int V, vector<vector<int>>& edges) {
vector<int> dist(V, INT_MAX);
dist[0] = 0;
// Relax all edges V - 1 times.
for (int i = 0; i < V - 1; i++) {
for (auto &edge : edges) {
int u = edge[0];
int v = edge[1];
int wt = edge[2];
if (dist[u] != INT_MAX && dist[u] + wt < dist[v])
dist[v] = dist[u] + wt;
if (dist[v] != INT_MAX && dist[v] + wt < dist[u])
dist[u] = dist[v] + wt;
}
}
return *max_element(dist.begin(), dist.end());
}
int main() {
int V = 4;
vector<vector<int>> edges = {
{0, 1, 2},
{1, 2, 1},
{2, 3, 3}
};
cout << distributedSystems(V, edges);
return 0;
}
class GFG {
static int distributedSystems(int V, int[][] edges) {
int[] dist = new int[V];
for (int i = 1; i < V; i++)
dist[i] = Integer.MAX_VALUE;
// Relax all edges V - 1 times.
for (int i = 0; i < V - 1; i++) {
for (int[] edge : edges) {
int u = edge[0];
int v = edge[1];
int wt = edge[2];
if (dist[u] != Integer.MAX_VALUE &&
dist[u] + wt < dist[v])
dist[v] = dist[u] + wt;
if (dist[v] != Integer.MAX_VALUE &&
dist[v] + wt < dist[u])
dist[u] = dist[v] + wt;
}
}
int ans = 0;
for (int x : dist)
ans = Math.max(ans, x);
return ans;
}
public static void main(String[] args) {
int V = 4;
int[][] edges = {
{0, 1, 2},
{1, 2, 1},
{2, 3, 3}
};
System.out.println(distributedSystems(V, edges));
}
}
def distributedSystems(v, edges):
dist = [float("inf")] * v
dist[0] = 0
# Relax all edges V - 1 times.
for _ in range(v - 1):
for u, x, wt in edges:
if dist[u] != float("inf") and dist[u] + wt < dist[x]:
dist[x] = dist[u] + wt
if dist[x] != float("inf") and dist[x] + wt < dist[u]:
dist[u] = dist[x] + wt
return max(dist)
if __name__ == "__main__":
v = 4
edges = [
[0, 1, 2],
[1, 2, 1],
[2, 3, 3]
]
print(distributedSystems(v, edges))
using System;
class GFG
{
static int distributedSystems(int V, int[][] edges)
{
int[] dist = new int[V];
for (int i = 1; i < V; i++)
dist[i] = int.MaxValue;
// Relax all edges V - 1 times.
for (int i = 0; i < V - 1; i++)
{
foreach (int[] edge in edges)
{
int u = edge[0];
int v = edge[1];
int wt = edge[2];
if (dist[u] != int.MaxValue &&
dist[u] + wt < dist[v])
dist[v] = dist[u] + wt;
if (dist[v] != int.MaxValue &&
dist[v] + wt < dist[u])
dist[u] = dist[v] + wt;
}
}
int ans = 0;
foreach (int x in dist)
ans = Math.Max(ans, x);
return ans;
}
static void Main()
{
int V = 4;
int[][] edges =
{
new int[] {0, 1, 2},
new int[] {1, 2, 1},
new int[] {2, 3, 3}
};
Console.WriteLine(distributedSystems(V, edges));
}
}
function distributedSystems(v, edges) {
const dist = new Array(v).fill(Infinity);
dist[0] = 0;
// Relax all edges V - 1 times.
for (let i = 0; i < v - 1; i++) {
for (const [u, x, wt] of edges) {
if (dist[u] !== Infinity && dist[u] + wt < dist[x])
dist[x] = dist[u] + wt;
if (dist[x] !== Infinity && dist[x] + wt < dist[u])
dist[u] = dist[x] + wt;
}
}
return Math.max(...dist);
}
// Driver Code
const v = 4;
const edges = [
[0, 1, 2],
[1, 2, 1],
[2, 3, 3]
];
console.log(distributedSystems(v, edges));
Output
6
[Expected Approach] Dijkstra's Shortest Path Algorithm - O((V + E) log V) Time and O(V + E) Space
The idea is to observe that a node receives the message as soon as it is reached through the shortest possible path from node 0. Since each node forwards the message immediately after receiving it, the minimum time required for a node to receive the message is equal to its shortest distance from the source. As all edge weights are positive, Dijkstra's algorithm efficiently computes these shortest distances, and the maximum among them gives the minimum time required for the message to reach every node.
Working of Approach:
- Build an adjacency list from the given edges.
- Initialize the distance of every node as infinity, except node 0, whose distance is 0.
- Use a min-heap to repeatedly process the node with the smallest current distance.
- For each adjacent node, update its distance if a shorter path is found and push the updated distance into the min-heap.
- After computing the shortest distance to every node, return the maximum distance among them.
#include <iostream>
#include <vector>
#include <queue>
#include <climits>
#include <algorithm>
using namespace std;
int distributedSystems(int V, vector<vector<int>> &edges) {
vector<vector<pair<int, int>>> adj(V);
for (auto &edge : edges) {
int u = edge[0];
int v = edge[1];
int wt = edge[2];
adj[u].push_back({v, wt});
adj[v].push_back({u, wt});
}
vector<int> dist(V, INT_MAX);
priority_queue<pair<int, int>, vector<pair<int, int>>,
greater<pair<int, int>>> pq;
dist[0] = 0;
pq.push({0, 0});
while (!pq.empty()) {
auto [d, u] = pq.top();
pq.pop();
if (d > dist[u])
continue;
for (auto &[v, wt] : adj[u]) {
if (dist[u] + wt < dist[v]) {
dist[v] = dist[u] + wt;
pq.push({dist[v], v});
}
}
}
return *max_element(dist.begin(), dist.end());
}
int main() {
int V = 4;
vector<vector<int>> edges = {
{0, 1, 2},
{1, 2, 1},
{2, 3, 3}
};
cout << distributedSystems(V, edges);
return 0;
}
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.PriorityQueue;
class GFG {
static int distributedSystems(int V, int[][] edges) {
List<int[]>[] adj = new ArrayList[V];
for (int i = 0; i < V; i++)
adj[i] = new ArrayList<>();
for (int[] edge : edges) {
int u = edge[0];
int v = edge[1];
int wt = edge[2];
adj[u].add(new int[]{v, wt});
adj[v].add(new int[]{u, wt});
}
int[] dist = new int[V];
Arrays.fill(dist, Integer.MAX_VALUE);
PriorityQueue<int[]> pq =
new PriorityQueue<>(Comparator.comparingInt(a -> a[0]));
dist[0] = 0;
pq.offer(new int[]{0, 0});
while (!pq.isEmpty()) {
int[] curr = pq.poll();
int d = curr[0];
int u = curr[1];
if (d > dist[u])
continue;
for (int[] next : adj[u]) {
int v = next[0];
int wt = next[1];
if (dist[u] + wt < dist[v]) {
dist[v] = dist[u] + wt;
pq.offer(new int[]{dist[v], v});
}
}
}
int ans = 0;
for (int x : dist)
ans = Math.max(ans, x);
return ans;
}
public static void main(String[] args) {
int V = 4;
int[][] edges = {
{0, 1, 2},
{1, 2, 1},
{2, 3, 3}
};
System.out.println(distributedSystems(V, edges));
}
}
import heapq
def distributedSystems(v, edges):
adj = [[] for _ in range(v)]
for u, x, wt in edges:
adj[u].append((x, wt))
adj[x].append((u, wt))
dist = [float("inf")] * v
dist[0] = 0
pq = [(0, 0)]
while pq:
d, u = heapq.heappop(pq)
if d > dist[u]:
continue
for x, wt in adj[u]:
if dist[u] + wt < dist[x]:
dist[x] = dist[u] + wt
heapq.heappush(pq, (dist[x], x))
return max(dist)
if __name__ == "__main__":
v = 4
edges = [
[0, 1, 2],
[1, 2, 1],
[2, 3, 3]
]
print(distributedSystems(v, edges))
using System;
using System.Collections.Generic;
class GFG
{
static int distributedSystems(int V, int[][] edges)
{
List<(int, int)>[] adj = new List<(int, int)>[V];
for (int i = 0; i < V; i++)
adj[i] = new List<(int, int)>();
foreach (int[] edge in edges)
{
int u = edge[0];
int v = edge[1];
int wt = edge[2];
adj[u].Add((v, wt));
adj[v].Add((u, wt));
}
int[] dist = new int[V];
Array.Fill(dist, int.MaxValue);
PriorityQueue<int, int> pq = new PriorityQueue<int, int>();
dist[0] = 0;
pq.Enqueue(0, 0);
while (pq.Count > 0)
{
int u = pq.Dequeue();
foreach (var (v, wt) in adj[u])
{
if (dist[u] != int.MaxValue &&
dist[u] + wt < dist[v])
{
dist[v] = dist[u] + wt;
pq.Enqueue(v, dist[v]);
}
}
}
int ans = 0;
foreach (int x in dist)
ans = Math.Max(ans, x);
return ans;
}
static void Main()
{
int V = 4;
int[][] edges =
{
new int[] {0, 1, 2},
new int[] {1, 2, 1},
new int[] {2, 3, 3}
};
Console.WriteLine(distributedSystems(V, edges));
}
}
class PriorityQueue {
constructor() {
this.heap = [];
}
push(item) {
this.heap.push(item);
let i = this.heap.length - 1;
while (i > 0) {
let p = (i - 1) >> 1;
if (this.heap[p][0] <= this.heap[i][0])
break;
[this.heap[p], this.heap[i]] =
[this.heap[i], this.heap[p]];
i = p;
}
}
pop() {
const top = this.heap[0];
const last = this.heap.pop();
if (this.heap.length) {
this.heap[0] = last;
let i = 0;
while (true) {
let left = 2 * i + 1;
let right = 2 * i + 2;
let smallest = i;
if (left < this.heap.length &&
this.heap[left][0] < this.heap[smallest][0])
smallest = left;
if (right < this.heap.length &&
this.heap[right][0] < this.heap[smallest][0])
smallest = right;
if (smallest === i)
break;
[this.heap[i], this.heap[smallest]] =
[this.heap[smallest], this.heap[i]];
i = smallest;
}
}
return top;
}
isEmpty() {
return this.heap.length === 0;
}
}
function distributedSystems(v, edges) {
const adj = Array.from({ length: v }, () => []);
for (const [u, x, wt] of edges) {
adj[u].push([x, wt]);
adj[x].push([u, wt]);
}
const dist = new Array(v).fill(Infinity);
dist[0] = 0;
const pq = new PriorityQueue();
pq.push([0, 0]);
while (!pq.isEmpty()) {
const [d, u] = pq.pop();
if (d > dist[u])
continue;
for (const [x, wt] of adj[u]) {
if (dist[u] + wt < dist[x]) {
dist[x] = dist[u] + wt;
pq.push([dist[x], x]);
}
}
}
return Math.max(...dist);
}
// Driver Code
const v = 4;
const edges = [
[0, 1, 2],
[1, 2, 1],
[2, 3, 3]
];
console.log(distributedSystems(v, edges));
Output
6