Given a connected graph with N vertices and M edges. The task is to print the lexicographically smallest DFS traversal of the graph starting from 1. Note that the vertices are numbered from 1 to N.
Examples:
Input: N = 5, M = 5, edges[] = {{1, 4}, {3, 4}, {5, 4}, {3, 2}, {1, 5}}
Output: 1 4 3 2 5
Input: N = 5, M = 8, edges[] = {{1, 4}, {3, 4}, {5, 4}, {3, 2}, {1, 5}, {1, 2}, {1, 3}, {3, 5}}
Output: 1 2 3 4 5
Approach: Instead of doing a normal DFS, first we have to sort the edges of each vertex, so that in each turn only the smallest edge is picked first. After sorting, just perform a normal DFS which will give the lexicographically smallest DFS traversal.
Below is the implementation of the above approach:
// C++ program to find the lexicographically // smallest traversal of a graph #include <bits/stdc++.h> using namespace std;
// Utility function to add an // edge to the graph void insertEdges( int u, int v, vector< int >* adj)
{ adj[u].push_back(v);
adj[v].push_back(u);
} // Function to perform DFS traversal void dfs(vector< int >* adj, int src, int n,
bool * visited)
{ // Print current vertex
cout << src << " " ;
// Mark it as visited
visited[src] = true ;
// Iterate over all the edges connected
// to this vertex
for ( int i = 0; i < adj[src].size(); i++) {
// If this vertex is not visited,
/// call dfs from this node
if (!visited[adj[src][i]])
dfs(adj, adj[src][i], n, visited);
}
} // Function to print the lexicographically // smallest DFS void printLexoSmall(vector< int >* adj, int n)
{ // A boolean array to keep track of
// nodes visited
bool visited[n + 1] = { 0 };
// Sort the edges of each vertex in
// ascending order
for ( int i = 0; i < n; i++)
sort(adj[i].begin(), adj[i].end());
// Call DFS
for ( int i = 1; i < n; i++) {
if (!visited[i])
dfs(adj, i, n, visited);
}
} // Driver code int main()
{ int n = 5, m = 5;
vector< int > adj[n + 1];
insertEdges(1, 4, adj);
insertEdges(3, 4, adj);
insertEdges(5, 4, adj);
insertEdges(3, 2, adj);
insertEdges(1, 5, adj);
insertEdges(1, 2, adj);
insertEdges(3, 5, adj);
insertEdges(1, 3, adj);
printLexoSmall(adj, n);
return 0;
} |
// Java program to find the lexicographically // smallest traversal of a graph import java.util.*;
class GFG
{ static boolean visited[];
static Vector<Vector<Integer>> adj = new Vector<Vector<Integer>>();
// Utility function to add an // edge to the graph static void insertEdges( int u, int v)
{ adj.get(u).add(v);
adj.get(v).add(u);
} // Function to perform DFS traversal static void dfs( int src, int n)
{ // Print current vertex
System.out.print( src + " " );
// Mark it as visited
visited[src] = true ;
// Iterate over all the edges connected
// to this vertex
for ( int i = 0 ; i < adj.get(src).size(); i++)
{
// If this vertex is not visited,
/// call dfs from this node
if (!visited[adj.get(src).get(i)])
dfs( adj.get(src).get(i), n);
}
} // Function to print the lexicographically // smallest DFS static void printLexoSmall( int n)
{ // A boolean array to keep track of
// nodes visited
visited= new boolean [n + 1 ];
// Sort the edges of each vertex in
// ascending order
for ( int i = 0 ; i < n; i++)
Collections.sort(adj.get(i));
// Call DFS
for ( int i = 1 ; i < n; i++)
{
if (!visited[i])
dfs( i, n);
}
} // Driver code public static void main(String args[])
{ int n = 5 , m = 5 ;
for ( int i = 0 ; i < n + 1 ; i++)
adj.add( new Vector<Integer>());
insertEdges( 1 , 4 );
insertEdges( 3 , 4 );
insertEdges( 5 , 4 );
insertEdges( 3 , 2 );
insertEdges( 1 , 5 );
insertEdges( 1 , 2 );
insertEdges( 3 , 5 );
insertEdges( 1 , 3 );
printLexoSmall( n);
} } // This code is contributed by Arnab Kundu |
# Python3 program to find the lexicographically # smallest traversal of a graph # Utility function to add an edge # to the graph def insertEdges(u, v, adj):
adj[u].append(v)
adj[v].append(u)
# Function to perform DFS traversal def dfs(adj, src, n, visited):
# Print current vertex
print (src, end = " " )
# Mark it as visited
visited[src] = True
# Iterate over all the edges
# connected to this vertex
for i in range ( 0 , len (adj[src])):
# If this vertex is not visited,
# call dfs from this node
if not visited[adj[src][i]]:
dfs(adj, adj[src][i], n, visited)
# Function to print the lexicographically # smallest DFS def printLexoSmall(adj, n):
# A boolean array to keep track
# of nodes visited
visited = [ 0 ] * (n + 1 )
# Sort the edges of each vertex
# in ascending order
for i in range ( 0 , n):
adj[i].sort()
# Call DFS
for i in range ( 1 , n):
if not visited[i]:
dfs(adj, i, n, visited)
# Driver code if __name__ = = "__main__" :
n, m = 5 , 5
adj = [[] for i in range (n + 1 )]
insertEdges( 1 , 4 , adj)
insertEdges( 3 , 4 , adj)
insertEdges( 5 , 4 , adj)
insertEdges( 3 , 2 , adj)
insertEdges( 1 , 5 , adj)
insertEdges( 1 , 2 , adj)
insertEdges( 3 , 5 , adj)
insertEdges( 1 , 3 , adj)
printLexoSmall(adj, n)
# This code is contributed by Rituraj Jain |
// C# program to find the lexicographically // smallest traversal of a graph using System;
using System.Collections.Generic;
class GFG
{ public static bool [] visited;
public static List<List< int >> adj = new List<List< int >>();
// Utility function to add an // edge to the graph public static void insertEdges( int u, int v)
{ adj[u].Add(v);
adj[v].Add(u);
} // Function to perform DFS traversal public static void dfs( int src, int n)
{ // Print current vertex
Console.Write(src + " " );
// Mark it as visited
visited[src] = true ;
// Iterate over all the edges connected
// to this vertex
for ( int i = 0; i < adj[src].Count; i++)
{
// If this vertex is not visited,
/// call dfs from this node
if (!visited[adj[src][i]])
{
dfs(adj[src][i], n);
}
}
} // Function to print the lexicographically // smallest DFS public static void printLexoSmall( int n)
{ // A boolean array to keep track of
// nodes visited
visited = new bool [n + 1];
// Sort the edges of each vertex in
// ascending order
for ( int i = 0; i < n; i++)
{
adj[i].Sort();
}
// Call DFS
for ( int i = 1; i < n; i++)
{
if (!visited[i])
{
dfs(i, n);
}
}
} // Driver code public static void Main( string [] args)
{ int n = 5, m = 5;
for ( int i = 0; i < n + 1; i++)
{
adj.Add( new List< int >());
}
insertEdges(1, 4);
insertEdges(3, 4);
insertEdges(5, 4);
insertEdges(3, 2);
insertEdges(1, 5);
insertEdges(1, 2);
insertEdges(3, 5);
insertEdges(1, 3);
printLexoSmall(n);
} } // This code is contributed by shrikanth13 |
<script> // Javascript program to find the lexicographically // smallest traversal of a graph let visited; let adj =[] ; // Utility function to add an // edge to the graph function insertEdges(u,v)
{ adj[u].push(v);
adj[v].push(u);
} // Function to perform DFS traversal function dfs(src,n)
{ // Print current vertex
document.write( src + " " );
// Mark it as visited
visited[src] = true ;
// Iterate over all the edges connected
// to this vertex
for (let i = 0; i < adj[src].length; i++)
{
// If this vertex is not visited,
/// call dfs from this node
if (!visited[adj[src][i]])
dfs( adj[src][i], n);
}
} // Function to print the lexicographically // smallest DFS function printLexoSmall(n)
{ // A boolean array to keep track of
// nodes visited
visited= new Array(n + 1);
// Sort the edges of each vertex in
// ascending order
for (let i = 0; i < n; i++)
adj[i].sort( function (a,b){ return a-b;});
// Call DFS
for (let i = 1; i < n; i++)
{
if (!visited[i])
dfs( i, n);
}
} // Driver code let n = 5, m = 5; for (let i = 0; i < n + 1; i++)
adj.push([]);
insertEdges(1, 4); insertEdges(3, 4); insertEdges(5, 4); insertEdges(3, 2); insertEdges(1, 5); insertEdges(1, 2); insertEdges(3, 5); insertEdges(1, 3); printLexoSmall( n); // This code is contributed by avanitrachhadiya2155 </script> |
1 2 3 4 5
Approach#2: Using DFS Algorithm with Priority Queue
This Approach builds a graph from the given edges, then performs a DFS traversal starting from node 1 using a priority queue to keep track of the lexicographically smallest path. The resulting path is returned as a list.
Algorithm
1. Build the adjacency list of the graph using the given edges.
2. Start the DFS from node 1 and push it into a priority queue.
3. While the priority queue is not empty, pop the node with the smallest value and visit it.
4. For each unvisited neighbor of the current node, push it into the priority queue.
5. Repeat steps 3-4 until all nodes are visited.
#include<bits/stdc++.h> using namespace std;
vector<vector< int >> build_graph(vector<vector< int >>& edges) {
vector<vector< int >> graph(edges.size() + 1);
for ( auto & edge : edges) {
graph[edge[0]].push_back(edge[1]);
graph[edge[1]].push_back(edge[0]);
}
return graph;
} vector< int > dfs(vector<vector< int >>& graph, int start) {
set< int > visited;
priority_queue< int , vector< int >, greater< int >> pq;
vector< int > result;
pq.push(start);
while (!pq.empty()) {
int node = pq.top();
pq.pop();
if (visited.count(node)) {
continue ;
}
visited.insert(node);
result.push_back(node);
for ( auto & neighbor : graph[node]) {
if (!visited.count(neighbor)) {
pq.push(neighbor);
}
}
}
return result;
} vector< int > lex_smallest_dfs( int n, int m, vector<vector< int >>& edges) {
auto graph = build_graph(edges);
return dfs(graph, 1);
} int main() {
int n = 5;
int m = 5;
vector<vector< int >> edges{{1, 4}, {3, 4}, {5, 4}, {3, 2}, {1, 5}};
auto result = lex_smallest_dfs(n, m, edges);
for ( auto & node : result) {
cout << node << " " ;
}
cout << endl;
return 0;
} // This code is contributed by Prajwal Kandekar |
import java.util.*;
public class Main {
public static List<List<Integer> >
buildGraph(List<List<Integer> > edges)
{
List<List<Integer> > graph
= new ArrayList<>(edges.size() + 1 );
for ( int i = 0 ; i < edges.size() + 1 ; i++) {
graph.add( new ArrayList<Integer>());
}
for (List<Integer> edge : edges) {
int u = edge.get( 0 );
int v = edge.get( 1 );
graph.get(u).add(v);
graph.get(v).add(u);
}
return graph;
}
public static List<Integer>
dfs(List<List<Integer> > graph, int start)
{
Set<Integer> visited = new HashSet<>();
PriorityQueue<Integer> pq = new PriorityQueue<>(
Comparator.comparingInt(a -> a));
List<Integer> result = new ArrayList<>();
pq.offer(start);
while (!pq.isEmpty()) {
int node = pq.poll();
if (visited.contains(node)) {
continue ;
}
visited.add(node);
result.add(node);
for ( int neighbor : graph.get(node)) {
if (!visited.contains(neighbor)) {
pq.offer(neighbor);
}
}
}
return result;
}
public static List<Integer>
lexSmallestDfs( int n, int m, List<List<Integer> > edges)
{
List<List<Integer> > graph = buildGraph(edges);
return dfs(graph, 1 );
}
public static void main(String[] args)
{
int n = 5 ;
int m = 5 ;
List<List<Integer> > edges = new ArrayList<>();
edges.add(Arrays.asList( 1 , 4 ));
edges.add(Arrays.asList( 3 , 4 ));
edges.add(Arrays.asList( 5 , 4 ));
edges.add(Arrays.asList( 3 , 2 ));
edges.add(Arrays.asList( 1 , 5 ));
List<Integer> result = lexSmallestDfs(n, m, edges);
for ( int node : result) {
System.out.print(node + " " );
}
System.out.println();
}
} |
import heapq
def build_graph(edges):
graph = [[] for _ in range ( len (edges) + 1 )]
for a, b in edges:
graph[a].append(b)
graph[b].append(a)
return graph
def dfs(graph, start):
visited = set ()
pq = [start]
result = []
while pq:
node = heapq.heappop(pq)
if node in visited:
continue
visited.add(node)
result.append(node)
for neighbor in graph[node]:
if neighbor not in visited:
heapq.heappush(pq, neighbor)
return result
def lex_smallest_dfs(n, m, edges):
graph = build_graph(edges)
return dfs(graph, 1 )
# Example usage: n = 5
m = 5
edges = [[ 1 , 4 ], [ 3 , 4 ], [ 5 , 4 ], [ 3 , 2 ], [ 1 , 5 ]]
print (lex_smallest_dfs(n, m, edges))
|
using System;
using System.Collections.Generic;
class Program
{ static List<List< int >> BuildGraph(List< int []> edges)
{
List<List< int >> graph = new List<List< int >>(edges.Count + 1);
for ( int i = 0; i <= edges.Count; i++)
{
graph.Add( new List< int >());
}
foreach ( int [] edge in edges)
{
graph[edge[0]].Add(edge[1]);
graph[edge[1]].Add(edge[0]);
}
return graph;
}
static List< int > DFS(List<List< int >> graph, int start)
{
HashSet< int > visited = new HashSet< int >();
Queue< int > queue = new Queue< int >();
List< int > result = new List< int >();
queue.Enqueue(start);
while (queue.Count > 0)
{
int node = queue.Dequeue();
if (visited.Contains(node))
{
continue ;
}
visited.Add(node);
result.Add(node);
foreach ( int neighbor in graph[node])
{
if (!visited.Contains(neighbor))
{
queue.Enqueue(neighbor);
}
}
}
return result;
}
static List< int > LexSmallestDFS( int n, int m, List< int []> edges)
{
List<List< int >> graph = BuildGraph(edges);
return DFS(graph, 1);
}
static void Main()
{
int n = 5;
int m = 5;
List< int []> edges = new List< int []>
{
new int [] { 1, 4 },
new int [] { 3, 4 },
new int [] { 5, 4 },
new int [] { 3, 2 },
new int [] { 1, 5 }
};
List< int > result = LexSmallestDFS(n, m, edges);
foreach ( int node in result)
{
Console.Write(node + " " );
}
Console.WriteLine();
}
} |
function buildGraph(edges) {
// create an empty array to hold graph nodes
let graph = new Array(edges.length + 1).fill().map(() => []);
for (let [u, v] of edges) {
// add the edge to the graph (undirected, so add it in both directions) graph[u].push(v);
graph[v].push(u);
}
return graph;
} function dfs(graph, start) {
// set to track visited nodes let visited = new Set();
// priority queue () to store nodes to be visited
let pq = [start];
// list to store the result in the order of visitation
let result = [];
while (pq.length > 0) {
// remove the node with the smallest label from the queue
let node = pq.shift();
// if it's already been visited, skip it
if (visited.has(node)) continue ;
// mark the node as visited
visited.add(node);
// add the node to the result list
result.push(node);
for (let neighbor of graph[node]) {
if (!visited.has(neighbor)) pq.push(neighbor);
}
pq.sort((a, b) => a - b); // sort the priority queue
}
return result;
} function lexSmallestDfs(n, m, edges) {
let graph = buildGraph(edges);
return dfs(graph, 1);
} // Example usage: let n = 5; let m = 5; let edges = [[1, 4], [3, 4], [5, 4], [3, 2], [1, 5]]; console.log(lexSmallestDfs(n, m, edges)); // output: [1, 4, 3, 2, 5]
|
[1, 4, 3, 2, 5]
Time Complexity: O(m log n) where m is the number of edges and n is the number of nodes in the graph.
Auxiliary Space: O(n+m)