Paths to travel each nodes using each edge (Seven Bridges of Königsberg)
Last Updated :
11 Mar, 2023
There are n nodes and m bridges in between these nodes. Print the possible path through each node using each edges (if possible), traveling through each edges only once.
Examples :
Input : [[0, 1, 0, 0, 1],
[1, 0, 1, 1, 0],
[0, 1, 0, 1, 0],
[0, 1, 1, 0, 0],
[1, 0, 0, 0, 0]]
Output : 5 -> 1 -> 2 -> 4 -> 3 -> 2
Input : [[0, 1, 0, 1, 1],
[1, 0, 1, 0, 1],
[0, 1, 0, 1, 1],
[1, 1, 1, 0, 0],
[1, 0, 1, 0, 0]]
Output : "No Solution"
It is one of the famous problems in Graph Theory and known as problem of “Seven Bridges of Königsberg”. This problem was solved by famous mathematician Leonhard Euler in 1735. This problem is also considered as the beginning of Graph Theory.
The problem back then was that: There was 7 bridges connecting 4 lands around the city of Königsberg in Prussia. Was there any way to start from any of the land and go through each of the bridges once and only once? Please see these wikipedia images for more clarity.
Euler first introduced graph theory to solve this problem. He considered each of the lands as a node of a graph and each bridge in between as an edge in between. Now he calculated if there is any Eulerian Path in that graph. If there is an Eulerian path then there is a solution otherwise not.
Problem here, is a generalized version of the problem in 1735.
Below is the implementation :
C++
#include <iostream>
#include <string.h>
#include <algorithm>
#include <list>
using namespace std;
class Graph
{
int V;
list< int > *adj;
public :
Graph( int V)
{
this ->V = V;
adj = new list< int >[V];
}
~Graph()
{
delete [] adj;
}
void addEdge( int u, int v)
{
adj[u].push_back(v);
adj[v].push_back(u);
}
void rmvEdge( int u, int v);
void printEulerTour();
void printEulerUtil( int s);
int DFSCount( int v, bool visited[]);
bool isValidNextEdge( int u, int v);
};
void Graph::printEulerTour()
{
int u = 0;
for ( int i = 0; i < V; i++)
if (adj[i].size() & 1)
{
u = i;
break ;
}
printEulerUtil(u);
cout << endl;
}
void Graph::printEulerUtil( int u)
{
list< int >::iterator i;
for (i = adj[u].begin(); i != adj[u].end(); ++i)
{
int v = *i;
if (v != -1 && isValidNextEdge(u, v))
{
cout << u << "-" << v << " " ;
rmvEdge(u, v);
printEulerUtil(v);
}
}
}
bool Graph::isValidNextEdge( int u, int v)
{
int count = 0;
list< int >::iterator i;
for (i = adj[u].begin(); i != adj[u].end(); ++i)
if (*i != -1)
count++;
if (count == 1)
return true ;
bool visited[V];
memset (visited, false , V);
int count1 = DFSCount(u, visited);
rmvEdge(u, v);
memset (visited, false , V);
int count2 = DFSCount(u, visited);
addEdge(u, v);
return (count1 > count2)? false : true ;
}
void Graph::rmvEdge( int u, int v)
{
list< int >::iterator iv = find(adj[u].begin(),
adj[u].end(), v);
*iv = -1;
list< int >::iterator iu = find(adj[v].begin(),
adj[v].end(), u);
*iu = -1;
}
int Graph::DFSCount( int v, bool visited[])
{
visited[v] = true ;
int count = 1;
list< int >::iterator i;
for (i = adj[v].begin(); i != adj[v].end(); ++i)
if (*i != -1 && !visited[*i])
count += DFSCount(*i, visited);
return count;
}
int main()
{
Graph g1(4);
g1.addEdge(0, 1);
g1.addEdge(0, 2);
g1.addEdge(1, 2);
g1.addEdge(2, 3);
g1.printEulerTour();
Graph g3(4);
g3.addEdge(0, 1);
g3.addEdge(1, 0);
g3.addEdge(0, 2);
g3.addEdge(2, 0);
g3.addEdge(2, 3);
g3.addEdge(3, 1);
g3.printEulerTour();
return 0;
}
|
Java
import java.util.*;
public class GFG{
static class Graph
{
int V;
ArrayList<ArrayList<Integer>> adj;
Graph( int V)
{
this .V = V;
adj = new ArrayList<ArrayList<Integer>>();
for ( int i= 0 ; i<V; i++){
adj.add( new ArrayList<Integer>());
}
}
void addEdge( int u, int v)
{
adj.get(u).add(v);
adj.get(v).add(u);
}
void rmvEdge( int u, int v)
{
int iv = find(adj.get(u), v);
adj.get(u).set(iv, - 1 );
int iu = find(adj.get(v), u);
adj.get(v).set(iu, - 1 );
}
int find(ArrayList<Integer> al, int v){
for ( int i= 0 ; i<al.size(); i++){
if (al.get(i) == v){
return i;
}
}
return - 1 ;
}
void printEulerTour()
{
int u = 0 ;
for ( int i = 0 ; i < V; i++){
if (adj.get(i).size() % 2 == 1 )
{
u = i;
break ;
}
}
printEulerUtil(u);
System.out.println();
}
void printEulerUtil( int u)
{
for ( int i = 0 ; i<adj.get(u).size(); ++i)
{
int v = adj.get(u).get(i);
if (v != - 1 && isValidNextEdge(u, v))
{
System.out.print(u + "-" + v + " " );
rmvEdge(u, v);
printEulerUtil(v);
}
}
}
int DFSCount( int v, boolean visited[])
{
visited[v] = true ;
int count = 1 ;
for ( int i = 0 ; i<adj.get(v).size(); ++i){
int u = adj.get(v).get(i);
if (u != - 1 && !visited[u]){
count += DFSCount(u, visited);
}
}
return count;
}
boolean isValidNextEdge( int u, int v)
{
int count = 0 ;
for ( int i = 0 ; i<adj.get(u).size(); ++i)
if (adj.get(u).get(i) != - 1 )
count++;
if (count == 1 )
return true ;
boolean visited[] = new boolean [V];
Arrays.fill(visited, false );
int count1 = DFSCount(u, visited);
rmvEdge(u, v);
Arrays.fill(visited, false );
int count2 = DFSCount(u, visited);
addEdge(u, v);
return (count1 > count2)? false : true ;
}
}
public static void main(String args[])
{
Graph g1 = new Graph( 4 );
g1.addEdge( 0 , 1 );
g1.addEdge( 0 , 2 );
g1.addEdge( 1 , 2 );
g1.addEdge( 2 , 3 );
g1.printEulerTour();
Graph g3 = new Graph( 4 );
g3.addEdge( 0 , 1 );
g3.addEdge( 1 , 0 );
g3.addEdge( 0 , 2 );
g3.addEdge( 2 , 0 );
g3.addEdge( 2 , 3 );
g3.addEdge( 3 , 1 );
g3.printEulerTour();
}
}
|
Python3
from collections import defaultdict
class Graph:
def __init__( self , V):
self .V = V
self .adj = defaultdict( list )
def addEdge( self , u, v):
self .adj[u].append(v)
self .adj[v].append(u)
def rmvEdge( self , u, v):
self .adj[u].remove(v)
self .adj[v].remove(u)
def printEulerTour( self ):
u = 0
for i in range ( self .V):
if len ( self .adj[i]) % 2 = = 1 :
u = i
break
self .printEulerUtil(u)
print ()
def printEulerUtil( self , u):
for v in self .adj[u]:
if v ! = - 1 and self .isValidNextEdge(u, v):
print (u, "-" , v, " " , end = "")
self .rmvEdge(u, v)
self .printEulerUtil(v)
def isValidNextEdge( self , u, v):
count = 0
for i in self .adj[u]:
if i ! = - 1 :
count + = 1
if count = = 1 :
return True
visited = [ False ] * ( self .V)
count1 = self .DFSCount(u, visited)
self .rmvEdge(u, v)
visited = [ False ] * ( self .V)
count2 = self .DFSCount(u, visited)
self .addEdge(u, v)
return False if count1 > count2 else True
def DFSCount( self , v, visited):
visited[v] = True
count = 1
for i in self .adj[v]:
if not visited[i]:
count + = self .DFSCount(i, visited)
return count
def makeEdge(src, dest):
graph.addEdge(src, dest)
def main():
g1 = Graph( 4 )
g1.addEdge( 0 , 1 )
g1.addEdge( 0 , 2 )
g1.addEdge( 1 , 2 )
g1.addEdge( 2 , 3 )
g1.printEulerTour()
g3 = Graph( 4 )
g3.addEdge( 0 , 1 )
g3.addEdge( 1 , 0 )
g3.addEdge( 0 , 2 )
g3.addEdge( 2 , 0 )
g3.addEdge( 2 , 3 )
g3.addEdge( 3 , 1 )
g3.printEulerTour()
if __name__ = = "__main__" :
main()
|
Javascript
class Graph {
constructor(V) {
this .V = V;
this .adj = Array.from(Array(V), () => new Array());
}
addEdge(u, v) {
this .adj[u].push(v);
this .adj[v].push(u);
}
rmvEdge(u, v) {
for (let i = 0; i < this .adj[u].length; i++) {
if ( this .adj[u][i] == v) {
this .adj[u][i] = -1;
break ;
}
}
for (let i = 0; i < this .adj[v].length; i++) {
if ( this .adj[v][i] == u) {
this .adj[v][i] = -1;
break ;
}
}
}
printEulerTour() {
let u = 0;
for (let i = 0; i < this .V; i++)
if ( this .adj[i].length & 1) {
u = i;
break ;
}
this .printEulerUtil(u);
console.log( " " );
}
printEulerUtil(u) {
{
for (let j in this .adj[u]) {
let v = this .adj[u][j];
if (v != -1 && this .isValidNextEdge(u, v)) {
console.log(u + "-" + v);
this .rmvEdge(u, v);
this .printEulerUtil(v);
}
}
}
}
DFSCount(v, visited) {
visited[v] = true ;
let count = 1;
for (let j in this .adj[v]) {
let i = this .adj[v][j];
if (i != -1 && !visited[i]) count += this .DFSCount(i, visited);
}
return count;
}
isValidNextEdge(u, v) {
let count = 0;
for (let j in this .adj[u]) {
let i = this .adj[u][j];
if (i != -1) count++;
}
if (count == 1) return true ;
let visited = new Array( this .V);
visited.fill( false );
let count1 = this .DFSCount(u, visited);
this .rmvEdge(u, v);
visited.fill( false );
let count2 = this .DFSCount(u, visited);
this .addEdge(u, v);
return count1 > count2 ? false : true ;
}
}
let g1 = new Graph(4);
g1.addEdge(0, 1);
g1.addEdge(0, 2);
g1.addEdge(1, 2);
g1.addEdge(2, 3);
g1.printEulerTour();
let g3 = new Graph(4);
g3.addEdge(0, 1);
g3.addEdge(1, 0);
g3.addEdge(0, 2);
g3.addEdge(2, 0);
g3.addEdge(2, 3);
g3.addEdge(3, 1);
g3.printEulerTour();
|
C#
using System;
using System.Collections.Generic;
class GFG {
class Graph {
int V;
List<List< int > > adj;
public Graph( int V)
{
this .V = V;
adj = new List<List< int > >();
for ( int i = 0; i < V; i++) {
adj.Add( new List< int >());
}
}
public void addEdge( int u, int v)
{
adj[u].Add(v);
adj[v].Add(u);
}
public void rmvEdge( int u, int v)
{
int iv = adj[u].IndexOf(v);
adj[u][iv] = -1;
int iu = adj[v].IndexOf(u);
adj[v][iu] = -1;
}
int find(List< int > al, int v)
{
for ( int i = 0; i < al.Count; i++) {
if (al[i] == v) {
return i;
}
}
return -1;
}
public void printEulerTour()
{
int u = 0;
for ( int i = 0; i < V; i++) {
if (adj[i].Count % 2 == 1) {
u = i;
break ;
}
}
printEulerUtil(u);
Console.WriteLine();
}
void printEulerUtil( int u)
{
for ( int i = 0; i < adj[u].Count; ++i) {
int v = adj[u][i];
if (v != -1 && isValidNextEdge(u, v)) {
Console.Write(u + "-" + v + " " );
rmvEdge(u, v);
printEulerUtil(v);
}
}
}
int DFSCount( int v, bool [] visited)
{
visited[v] = true ;
int count = 1;
for ( int i = 0; i < adj[v].Count; ++i) {
int u = adj[v][i];
if (u != -1 && !visited[u]) {
count += DFSCount(u, visited);
}
}
return count;
}
bool isValidNextEdge( int u, int v)
{
int count = 0;
for ( int i = 0; i < adj[u].Count; ++i)
if (adj[u][i] != -1)
count++;
if (count == 1)
return true ;
bool [] visited = new bool [V];
Array.Fill(visited, false );
int count1 = DFSCount(u, visited);
rmvEdge(u, v);
Array.Fill(visited, false );
int count2 = DFSCount(u, visited);
addEdge(u, v);
return (count1 > count2) ? false : true ;
}
}
public static void Main()
{
Graph g1 = new Graph(4);
g1.addEdge(0, 1);
g1.addEdge(0, 2);
g1.addEdge(1, 2);
g1.addEdge(2, 3);
g1.printEulerTour();
Graph g3 = new Graph(4);
g3.addEdge(0, 1);
g3.addEdge(1, 0);
g3.addEdge(0, 2);
g3.addEdge(2, 0);
g3.addEdge(2, 3);
g3.addEdge(3, 1);
g3.printEulerTour();
}
}
|
Output:
2-0 0-1 1-2 2-3
1-0 0-2 2-3 3-1 1-0 0-2
Time Complexity: O(V+E)
The time complexity of the above algorithm is O(V+E) where V is the number of vertices and E is the number of edges in the graph.
Space Complexity: O(V+E)
The space complexity of the above algorithm is O(V+E) where V is the number of vertices and E is the number of edges in the graph.
Please Login to comment...