Given a directed graph with V vertices labeled from 0 to V-1 and a list of edges edges[][], where each edge is represented as [u, v] indicating a directed edge from vertex u to vertex v, find a Mother Vertex of the graph.
A Mother Vertex is a vertex from which all other vertices can be reached.
- If multiple such vertices exist, return the one with the smallest value.
- If no such vertex exists, return -1.
Example:
Input: V = 7, edges[][] = [[0, 1], [0, 2], [1, 3], [4, 1], [6, 4], [5, 6], [5, 2], [6, 0]]
Output: 5
Explanation: As shown in the above graph.Input: V = 5, edges[][] = [[0, 2], [0, 3], [1, 0], [2, 1], [3, 4]]
Output: 0
Explanation: Vertices 0, 1, and 2 can each reach all other vertices in the graph. Among them, 0 is the smallest, so the output is 0.
Table of Content
[Naive Approach] - Using BFS(Breadth First Search) - O(V * (E + V)) Time and O(V) Space
A straightforward (brute-force) approach is to run BFS (or DFS) from every vertex and check whether all other vertices are reachable from it. If such a vertex exists, it is a mother vertex. However, this approach is inefficient, as it requires performing a traversal for each vertex.
#include <bits/stdc++.h>
using namespace std;
// BFS traversal starting from a vertex
void bfsFromVertex(int v, vector<bool> &visited, vector<vector<int>> &adj)
{
queue<int> q;
// Mark starting vertex visited
visited[v] = true;
q.push(v);
while (!q.empty())
{
int node = q.front();
q.pop();
for (int neighbor : adj[node])
{
if (!visited[neighbor])
{
visited[neighbor] = true;
q.push(neighbor);
}
}
}
}
// Function to find a mother vertex using BFS
int findMotherVertex(int V, vector<vector<int>> &edges)
{
// Adjacency list
vector<vector<int>> adj(V);
for (auto &edge : edges)
{
adj[edge[0]].push_back(edge[1]);
}
// Try BFS from every vertex
for (int i = 0; i < V; i++)
{
vector<bool> visited(V, false);
bfsFromVertex(i, visited, adj);
// Check if all nodes are visited
bool allVisited = true;
for (bool v : visited)
{
if (!v)
{
allVisited = false;
break;
}
}
if (allVisited)
return i;
}
return -1;
}
int main()
{
int V = 7;
vector<vector<int>> edges = {{0, 1}, {0, 2}, {1, 3}, {4, 1}, {6, 4}, {5, 6}, {5, 2}, {6, 0}};
cout << findMotherVertex(V, edges) << endl;
return 0;
}
import java.util.*;
public class GFG {
// BFS traversal starting from a vertex
static void bfsFromVertex(int v, boolean[] visited,
List<List<Integer> > adj)
{
Queue<Integer> q = new LinkedList<>();
// Mark starting vertex visited
visited[v] = true;
q.add(v);
while (!q.isEmpty()) {
int node = q.poll();
for (int neighbor : adj.get(node)) {
if (!visited[neighbor]) {
visited[neighbor] = true;
q.add(neighbor);
}
}
}
}
// Function to find a mother vertex using BFS
static int findMotherVertex(int V, int[][] edges)
{
// Adjacency list
List<List<Integer> > adj = new ArrayList<>();
for (int i = 0; i < V; i++) {
adj.add(new ArrayList<>());
}
for (int[] edge : edges) {
adj.get(edge[0]).add(edge[1]);
}
// Try BFS from every vertex
for (int i = 0; i < V; i++) {
boolean[] visited = new boolean[V];
bfsFromVertex(i, visited, adj);
// Check if all nodes are visited
boolean allVisited = true;
for (boolean v : visited) {
if (!v) {
allVisited = false;
break;
}
}
if (allVisited)
return i;
}
return -1;
}
public static void main(String[] args)
{
int V = 7;
int[][] edges
= { { 0, 1 }, { 0, 2 }, { 1, 3 }, { 4, 1 },
{ 6, 4 }, { 5, 6 }, { 5, 2 }, { 6, 0 } };
System.out.println(findMotherVertex(V, edges));
}
}
from collections import deque
# BFS traversal starting from a vertex
def bfsFromVertex(v, visited, adj):
q = deque()
# Mark starting vertex visited
visited[v] = True
q.append(v)
while q:
node = q.popleft()
for neighbor in adj[node]:
if not visited[neighbor]:
visited[neighbor] = True
q.append(neighbor)
# Function to find a mother vertex using BFS
def findMotherVertex(V, edges):
# Adjacency list
adj = [[] for _ in range(V)]
for u, v in edges:
adj[u].append(v)
# Try BFS from every vertex
for i in range(V):
visited = [False] * V
bfsFromVertex(i, visited, adj)
# Check if all nodes are visited
if all(visited):
return i
return -1
# Driver code
if __name__ == "__main__":
V = 7
edges = [
[0, 1], [0, 2], [1, 3], [4, 1],
[6, 4], [5, 6], [5, 2], [6, 0]]
print(findMotherVertex(V, edges))
using System;
using System.Collections.Generic;
class GFG {
// BFS traversal starting from a vertex
static void bfsFromVertex(int v, bool[] visited,
List<List<int> > adj)
{
Queue<int> q = new Queue<int>();
// Mark starting vertex visited
visited[v] = true;
q.Enqueue(v);
while (q.Count > 0) {
int node = q.Dequeue();
foreach(int neighbor in adj[node])
{
if (!visited[neighbor]) {
visited[neighbor] = true;
q.Enqueue(neighbor);
}
}
}
}
// Function to find a mother vertex using BFS
static int findMotherVertex(int V, int[][] edges)
{
// Adjacency list
List<List<int> > adj = new List<List<int> >();
for (int i = 0; i < V; i++) {
adj.Add(new List<int>());
}
foreach(var edge in edges)
{
adj[edge[0]].Add(edge[1]);
}
// Try BFS from every vertex
for (int i = 0; i < V; i++) {
bool[] visited = new bool[V];
bfsFromVertex(i, visited, adj);
// Check if all nodes are visited
bool allVisited = true;
foreach(bool v in visited)
{
if (!v) {
allVisited = false;
break;
}
}
if (allVisited)
return i;
}
return -1;
}
static void Main()
{
int V = 7;
int[][] edges = new int[][] {
new int[] { 0, 1 }, new int[] { 0, 2 },
new int[] { 1, 3 }, new int[] { 4, 1 },
new int[] { 6, 4 }, new int[] { 5, 6 },
new int[] { 5, 2 }, new int[] { 6, 0 }
};
Console.WriteLine(findMotherVertex(V, edges));
}
}
// BFS traversal starting from a vertex
function bfsFromVertex(v, visited, adj)
{
let q = [];
// Mark starting vertex visited
visited[v] = true;
q.push(v);
while (q.length > 0) {
let node = q.shift();
for (let neighbor of adj[node]) {
if (!visited[neighbor]) {
visited[neighbor] = true;
q.push(neighbor);
}
}
}
}
// Function to find a mother vertex using BFS
function findMotherVertex(V, edges)
{
// Adjacency list
let adj = Array.from({length : V}, () => []);
for (let [u, v] of edges) {
adj[u].push(v);
}
// Try BFS from every vertex
for (let i = 0; i < V; i++) {
let visited = new Array(V).fill(false);
bfsFromVertex(i, visited, adj);
// Check if all nodes are visited
let allVisited = visited.every(v => v === true);
if (allVisited)
return i;
}
return -1;
}
// Driver code
let V = 7;
let edges = [
[ 0, 1 ], [ 0, 2 ], [ 1, 3 ], [ 4, 1 ], [ 6, 4 ],
[ 5, 6 ], [ 5, 2 ], [ 6, 0 ]];
console.log(findMotherVertex(V, edges));
[Expected Approach] - Using DFS (Last Finished Vertex Technique) - O(V + E) Time and O(V) Space
The approach is that if a mother vertex exists in a directed graph, it will be the last vertex to finish in a DFS traversal. This is because DFS may start from multiple unvisited vertices, forming a DFS forest. A mother vertex can reach all other vertices, so when DFS eventually starts from it, it will traverse the entire remaining graph in one go and finish last. Any earlier DFS starting points cannot reach all nodes (otherwise they would also be mother vertices). Therefore, the last finished vertex is the only possible candidate, and we finally verify it by checking whether it can reach all vertices.
Consider the following dry run:
V = 7, Edges = {{0, 1}, {0, 2}, {1, 3}, {4, 1}, {6, 4}, {5, 6}, {5, 2}, {6, 0}}
- Step 1: Build Adjacency List
0 --> {1, 2}, 1 --> {3}, 4 --> {1}, 5 --> {2, 6}, 6 --> {0, 4} - Step 2: Perform DFS on all vertices
For v = 0 --> DFS: 0 -> 1 -> 3 -> 2 --> visited = {0, 1, 2, 3} --> candidate = 0
For v = 1, 2, 3 --> already visited --> skip
For v = 4 --> DFS: 4 -> 1 (already visited) --> visited = {0, 1, 2, 3, 4} --> candidate = 4
For v = 5 --> DFS: 5 -> 6 -> 0 (already visited), 6 -> 4(already visited) -->
visited = {0, 1, 2, 3, 4, 5, 6} --> candidate = 5
For v = 6 --> already visited --> skip - Step 3: Verify the candidate
Start DFS from vertex 5: visit 5 -> 6 -> 4 -> 1 -> 3 and 6 -> 0 -> 2 ---> visited = {0, 1, 2, 3, 4, 5, 6}
All vertices are reachable from 5 and hence, 5 is a mother vertex.
Final answer : 5
#include <bits/stdc++.h>
using namespace std;
// DFS traversal starting from a vertex
void dfsFromVertex(int v, vector<bool> &visited, vector<vector<int>> &adj)
{
// Mark vertex visited
visited[v] = true;
for (int neighbor : adj[v])
{
if (!visited[neighbor])
{
dfsFromVertex(neighbor, visited, adj);
}
}
}
// Function to find a mother vertex
int findMotherVertex(int V, vector<vector<int>> &edges)
{
// Adjacency list
vector<vector<int>> adj(V);
for (auto &edge : edges)
{
int u = edge[0];
int v = edge[1];
adj[u].push_back(v);
}
vector<bool> visited(V, false);
int candidate = 0;
// Step 1: Find last finished vertex
for (int i = 0; i < V; i++)
{
if (!visited[i])
{
dfsFromVertex(i, visited, adj);
// Candidate mother vertex
candidate = i;
}
}
// Step 2: Check if candidate reaches all vertices
fill(visited.begin(), visited.end(), false);
dfsFromVertex(candidate, visited, adj);
for (bool v : visited)
if (!v)
return -1;
return candidate;
}
int main()
{
int V = 7;
vector<vector<int>> edges = {{0, 1}, {0, 2}, {1, 3}, {4, 1}, {6, 4}, {5, 6}, {5, 2}, {6, 0}};
cout << findMotherVertex(V, edges) << endl;
return 0;
}
import java.util.*;
public class GFG {
// DFS traversal starting from a vertex
static void dfsFromVertex(int v, boolean[] visited,
List<List<Integer> > adj)
{
// Mark vertex visited
visited[v] = true;
for (int neighbor : adj.get(v)) {
if (!visited[neighbor]) {
dfsFromVertex(neighbor, visited, adj);
}
}
}
// Function to find a mother vertex
static int findMotherVertex(int V, int[][] edges)
{
// Adjacency list
List<List<Integer> > adj = new ArrayList<>();
for (int i = 0; i < V; i++) {
adj.add(new ArrayList<>());
}
for (int[] edge : edges) {
int u = edge[0];
int v = edge[1];
adj.get(u).add(v);
}
boolean[] visited = new boolean[V];
int candidate = 0;
// Step 1: Find last finished vertex
for (int i = 0; i < V; i++) {
if (!visited[i]) {
dfsFromVertex(i, visited, adj);
// Candidate mother vertex
candidate = i;
}
}
// Step 2: Check if candidate reaches all vertices
Arrays.fill(visited, false);
dfsFromVertex(candidate, visited, adj);
for (boolean v : visited)
if (!v)
return -1;
return candidate;
}
public static void main(String[] args)
{
int V = 7;
int[][] edges
= { { 0, 1 }, { 0, 2 }, { 1, 3 }, { 4, 1 },
{ 6, 4 }, { 5, 6 }, { 5, 2 }, { 6, 0 } };
System.out.println(findMotherVertex(V, edges));
}
}
# DFS traversal starting from a vertex
def dfsFromVertex(v, visited, adj):
# Mark vertex visited
visited[v] = True
for neighbor in adj[v]:
if not visited[neighbor]:
dfsFromVertex(neighbor, visited, adj)
# Function to find a mother vertex
def findMotherVertex(V, edges):
# Adjacency list
adj = [[] for _ in range(V)]
for edge in edges:
u = edge[0]
v = edge[1]
adj[u].append(v)
visited = [False] * V
candidate = 0
# Step 1: Find last finished vertex
for i in range(V):
if not visited[i]:
dfsFromVertex(i, visited, adj)
# Candidate mother vertex
candidate = i
# Step 2: Check if candidate reaches all vertices
visited = [False] * V
dfsFromVertex(candidate, visited, adj)
for v in visited:
if not v:
return -1
return candidate
# Driver code
if __name__ == "__main__":
V = 7
edges = [
[0, 1], [0, 2], [1, 3], [4, 1],
[6, 4], [5, 6], [5, 2], [6, 0]]
print(findMotherVertex(V, edges))
using System;
using System.Collections.Generic;
class GFG {
// DFS traversal starting from a vertex
static void dfsFromVertex(int v, bool[] visited,
List<List<int> > adj)
{
// Mark vertex visited
visited[v] = true;
foreach(int neighbor in adj[v])
{
if (!visited[neighbor]) {
dfsFromVertex(neighbor, visited, adj);
}
}
}
// Function to find a mother vertex
static int findMotherVertex(int V, int[][] edges)
{
// Adjacency list
List<List<int> > adj = new List<List<int> >();
for (int i = 0; i < V; i++) {
adj.Add(new List<int>());
}
foreach(var edge in edges)
{
int u = edge[0];
int v = edge[1];
adj[u].Add(v);
}
bool[] visited = new bool[V];
int candidate = 0;
// Step 1: Find last finished vertex
for (int i = 0; i < V; i++) {
if (!visited[i]) {
dfsFromVertex(i, visited, adj);
// Candidate mother vertex
candidate = i;
}
}
// Step 2: Check if candidate reaches all vertices
Array.Fill(visited, false);
dfsFromVertex(candidate, visited, adj);
foreach(bool v in visited) if (!v) return -1;
return candidate;
}
static void Main()
{
int V = 7;
int[][] edges = new int[][] {
new int[] { 0, 1 }, new int[] { 0, 2 },
new int[] { 1, 3 }, new int[] { 4, 1 },
new int[] { 6, 4 }, new int[] { 5, 6 },
new int[] { 5, 2 }, new int[] { 6, 0 }
};
Console.WriteLine(findMotherVertex(V, edges));
}
}
// DFS traversal starting from a vertex
function dfsFromVertex(v, visited, adj)
{
// Mark vertex visited
visited[v] = true;
for (let neighbor of adj[v]) {
if (!visited[neighbor]) {
dfsFromVertex(neighbor, visited, adj);
}
}
}
// Function to find a mother vertex
function findMotherVertex(V, edges)
{
// Adjacency list
let adj = Array.from({length : V}, () => []);
for (let edge of edges) {
let u = edge[0];
let v = edge[1];
adj[u].push(v);
}
let visited = new Array(V).fill(false);
let candidate = 0;
// Step 1: Find last finished vertex
for (let i = 0; i < V; i++) {
if (!visited[i]) {
dfsFromVertex(i, visited, adj);
// Candidate mother vertex
candidate = i;
}
}
// Step 2: Check if candidate reaches all vertices
visited.fill(false);
dfsFromVertex(candidate, visited, adj);
for (let v of visited)
if (!v)
return -1;
return candidate;
}
// Driver code
let V = 7;
let edges = [
[ 0, 1 ], [ 0, 2 ], [ 1, 3 ], [ 4, 1 ], [ 6, 4 ],
[ 5, 6 ], [ 5, 2 ], [ 6, 0 ]
];
console.log(findMotherVertex(V, edges));
Output
5
