Learnitweb

Finding shortest path with topological ordering

1. Introduction

In this tutorial, we’ll discuss about finding the shortest path with topological ordering. Usually we use Dijkstra’s algorithm if we want to find the shortest path in an arbitrary graph G(V,E) graph.

But if the graph is a directed acyclic graph, we can achieve linear running time to calculate the shortest path in a G(V,E) directed acyclic graph. We can find the shortest path in a directed acyclic graph (DAG) with topological ordering in O(V+E) linear running time. It only works when a valid topological order exists.

2. Pseudocode

Following is the pseudocode:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
function shortestPathDAG(graph, start):
# Step 1: Perform topological sort
topoOrder = topologicalSort(graph)
# Step 2: Initialize distances
distance = [] * number_of_vertices
distance[start] = 0
# Step 3: Relax edges in topological order
for vertex in topoOrder:
for (neighbor, weight) in graph[vertex]:
distance[neighbor] = min(distance[neighbor], distance[vertex] + weight)
return distance
function shortestPathDAG(graph, start): # Step 1: Perform topological sort topoOrder = topologicalSort(graph) # Step 2: Initialize distances distance = [∞] * number_of_vertices distance[start] = 0 # Step 3: Relax edges in topological order for vertex in topoOrder: for (neighbor, weight) in graph[vertex]: distance[neighbor] = min(distance[neighbor], distance[vertex] + weight) return distance
function shortestPathDAG(graph, start):
    # Step 1: Perform topological sort
    topoOrder = topologicalSort(graph)

    # Step 2: Initialize distances
    distance = [∞] * number_of_vertices
    distance[start] = 0

    # Step 3: Relax edges in topological order
    for vertex in topoOrder:
        for (neighbor, weight) in graph[vertex]:
            distance[neighbor] = min(distance[neighbor], distance[vertex] + weight)

    return distance

In the following figure S is the source vertex which is the starting point. We calculate the shortest path to every other vertex starting with the s vertex. If we find a shorter path to the vertex v via u vertex then we have to check if distance[u] + w < distance[v] which means we have found a shorter path.

3. Implementation

Now, we’ll find the shortest path of the following graph:

Vertex.java

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
import java.util.ArrayList;
import java.util.List;
public class Vertex {
private String name;
private boolean visited;
//shortest path from the source vertex to actual vertex
private int minDistance;
//the previous node in the shortest path
private Vertex predecessor;
private List<Edge> adjacencyList;
public Vertex(String name){
this.name=name;
this.minDistance = Integer.MAX_VALUE;
this.adjacencyList = new ArrayList<>();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isVisited() {
return visited;
}
public void setVisited(boolean visited) {
this.visited = visited;
}
public int getMinDistance() {
return minDistance;
}
public void setMinDistance(int minDistance) {
this.minDistance = minDistance;
}
public Vertex getPredecessor() {
return predecessor;
}
public void setPredecessor(Vertex predecessor) {
this.predecessor = predecessor;
}
public List<Edge> getNeighbors() {
return adjacencyList;
}
public void addNeighbor(Edge edge) {
this.adjacencyList.add(edge);
}
@Override
public String toString() {
return "Vertex{" +
"name='" + name + '\'' +
", predecessor=" + predecessor +
'}';
}
}
import java.util.ArrayList; import java.util.List; public class Vertex { private String name; private boolean visited; //shortest path from the source vertex to actual vertex private int minDistance; //the previous node in the shortest path private Vertex predecessor; private List<Edge> adjacencyList; public Vertex(String name){ this.name=name; this.minDistance = Integer.MAX_VALUE; this.adjacencyList = new ArrayList<>(); } public String getName() { return name; } public void setName(String name) { this.name = name; } public boolean isVisited() { return visited; } public void setVisited(boolean visited) { this.visited = visited; } public int getMinDistance() { return minDistance; } public void setMinDistance(int minDistance) { this.minDistance = minDistance; } public Vertex getPredecessor() { return predecessor; } public void setPredecessor(Vertex predecessor) { this.predecessor = predecessor; } public List<Edge> getNeighbors() { return adjacencyList; } public void addNeighbor(Edge edge) { this.adjacencyList.add(edge); } @Override public String toString() { return "Vertex{" + "name='" + name + '\'' + ", predecessor=" + predecessor + '}'; } }
import java.util.ArrayList;
import java.util.List;

public class Vertex {
    private String name;
    private boolean visited;
    //shortest path from the source vertex to actual vertex
    private int minDistance;
    //the previous node in the shortest path
    private Vertex predecessor;
    private List<Edge> adjacencyList;

    public Vertex(String name){
        this.name=name;
        this.minDistance = Integer.MAX_VALUE;
        this.adjacencyList = new ArrayList<>();
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public boolean isVisited() {
        return visited;
    }

    public void setVisited(boolean visited) {
        this.visited = visited;
    }

    public int getMinDistance() {
        return minDistance;
    }

    public void setMinDistance(int minDistance) {
        this.minDistance = minDistance;
    }

    public Vertex getPredecessor() {
        return predecessor;
    }

    public void setPredecessor(Vertex predecessor) {
        this.predecessor = predecessor;
    }

    public List<Edge> getNeighbors() {
        return adjacencyList;
    }

    public void addNeighbor(Edge edge) {
        this.adjacencyList.add(edge);
    }

    @Override
    public String toString() {
        return "Vertex{" +
                "name='" + name + '\'' +
                ", predecessor=" + predecessor +
                '}';
    }
}

Edge.java

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
public class Edge {
private Vertex target;
private int weight;
public Edge(Vertex target, int weight){
this.target = target;
this.weight = weight;
}
public Vertex getTarget() {
return target;
}
public int getWeight() {
return weight;
}
}
public class Edge { private Vertex target; private int weight; public Edge(Vertex target, int weight){ this.target = target; this.weight = weight; } public Vertex getTarget() { return target; } public int getWeight() { return weight; } }
public class Edge {
    private Vertex target;
    private int weight;

    public Edge(Vertex target, int weight){
        this.target = target;
        this.weight = weight;
    }

    public Vertex getTarget() {
        return target;
    }

    public int getWeight() {
        return weight;
    }
}

TopologicalOrdering.java

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
import java.util.Stack;
import java.util.List;
public class TopologicalOrdering {
private Stack<Vertex> stack;
public TopologicalOrdering(List<Vertex> graph){
this.stack = new Stack<>();
for(int i=0; i<graph.size(); i++){
if(!graph.get(i).isVisited()){
dfs(graph.get(i));
}
}
}
public void dfs(Vertex vertex){
vertex.setVisited(true);
//for all the neighbors of a vertex
for(Edge e: vertex.getNeighbors()){
if(!e.getTarget().isVisited()){
dfs(e.getTarget());
}
}
stack.push(vertex);
}
public Stack<Vertex> getStack(){
return this.stack;
}
}
import java.util.Stack; import java.util.List; public class TopologicalOrdering { private Stack<Vertex> stack; public TopologicalOrdering(List<Vertex> graph){ this.stack = new Stack<>(); for(int i=0; i<graph.size(); i++){ if(!graph.get(i).isVisited()){ dfs(graph.get(i)); } } } public void dfs(Vertex vertex){ vertex.setVisited(true); //for all the neighbors of a vertex for(Edge e: vertex.getNeighbors()){ if(!e.getTarget().isVisited()){ dfs(e.getTarget()); } } stack.push(vertex); } public Stack<Vertex> getStack(){ return this.stack; } }
import java.util.Stack;
import java.util.List;

public class TopologicalOrdering {

    private Stack<Vertex> stack;

    public TopologicalOrdering(List<Vertex> graph){
        this.stack = new Stack<>();
        for(int i=0; i<graph.size(); i++){
            if(!graph.get(i).isVisited()){
                dfs(graph.get(i));
            }
        }
    }

    public void dfs(Vertex vertex){
        vertex.setVisited(true);

        //for all the neighbors of a vertex
        for(Edge e: vertex.getNeighbors()){
            if(!e.getTarget().isVisited()){
                dfs(e.getTarget());
            }
        }
        stack.push(vertex);
    }

    public Stack<Vertex> getStack(){
        return this.stack;
    }
}

ShortestPath.java

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
import java.util.List;
import java.util.Stack;
public class ShortestPath {
private TopologicalOrdering topologicalOrdering;
public ShortestPath(List<Vertex> graph){
this.topologicalOrdering = new TopologicalOrdering(graph);
graph.get(0).setMinDistance(0);
}
public void compute(){
Stack<Vertex> topologicalOrder = topologicalOrdering.getStack();
while(!topologicalOrder.isEmpty()){
Vertex u = topologicalOrder.pop();
if(u.getMinDistance() == Integer.MAX_VALUE) continue;
for(Edge e: u.getNeighbors()){
Vertex v = e.getTarget();
if(v.getMinDistance() > u.getMinDistance() + e.getWeight()){
v.setMinDistance(u.getMinDistance()+e.getWeight());
v.setPredecessor(u);
}
}
}
}
}
import java.util.List; import java.util.Stack; public class ShortestPath { private TopologicalOrdering topologicalOrdering; public ShortestPath(List<Vertex> graph){ this.topologicalOrdering = new TopologicalOrdering(graph); graph.get(0).setMinDistance(0); } public void compute(){ Stack<Vertex> topologicalOrder = topologicalOrdering.getStack(); while(!topologicalOrder.isEmpty()){ Vertex u = topologicalOrder.pop(); if(u.getMinDistance() == Integer.MAX_VALUE) continue; for(Edge e: u.getNeighbors()){ Vertex v = e.getTarget(); if(v.getMinDistance() > u.getMinDistance() + e.getWeight()){ v.setMinDistance(u.getMinDistance()+e.getWeight()); v.setPredecessor(u); } } } } }
import java.util.List;
import java.util.Stack;

public class ShortestPath {

    private TopologicalOrdering topologicalOrdering;

    public ShortestPath(List<Vertex> graph){
        this.topologicalOrdering = new TopologicalOrdering(graph);
        graph.get(0).setMinDistance(0);
    }

    public void compute(){
        Stack<Vertex> topologicalOrder = topologicalOrdering.getStack();
        while(!topologicalOrder.isEmpty()){
            Vertex u = topologicalOrder.pop();
            if(u.getMinDistance() == Integer.MAX_VALUE) continue;
            for(Edge e: u.getNeighbors()){
                Vertex v = e.getTarget();
                if(v.getMinDistance() > u.getMinDistance() + e.getWeight()){
                    v.setMinDistance(u.getMinDistance()+e.getWeight());
                    v.setPredecessor(u);
                }
            }
        }
    }
}

App.java

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
import java.util.List;
import java.util.ArrayList;
import java.util.Stack;
public class App {
public static void main(String args[]){
List<Vertex> graph = new ArrayList();
Vertex v0 = new Vertex("S");
Vertex v1 = new Vertex("A");
Vertex v2 = new Vertex("B");
Vertex v3 = new Vertex("C");
Vertex v4 = new Vertex("D");
Vertex v5 = new Vertex("E");
v0.addNeighbor(new Edge(v1, 1));
v0.addNeighbor(new Edge(v3, 2));
v1.addNeighbor(new Edge(v2, 6));
v2.addNeighbor(new Edge(v4, 1));
v2.addNeighbor(new Edge(v5, 2));
v3.addNeighbor(new Edge(v1, 4));
v3.addNeighbor(new Edge(v4, 3));
v4.addNeighbor(new Edge(v5, 1));
graph.add(v0);
graph.add(v1);
graph.add(v2);
graph.add(v3);
graph.add(v4);
graph.add(v5);
ShortestPath algorithm = new ShortestPath(graph);
algorithm.compute();
for(Vertex v: graph){
System.out.println("Distance from s: " + v.getMinDistance() + " - " + v.getPredecessor());
}
}
}
import java.util.List; import java.util.ArrayList; import java.util.Stack; public class App { public static void main(String args[]){ List<Vertex> graph = new ArrayList(); Vertex v0 = new Vertex("S"); Vertex v1 = new Vertex("A"); Vertex v2 = new Vertex("B"); Vertex v3 = new Vertex("C"); Vertex v4 = new Vertex("D"); Vertex v5 = new Vertex("E"); v0.addNeighbor(new Edge(v1, 1)); v0.addNeighbor(new Edge(v3, 2)); v1.addNeighbor(new Edge(v2, 6)); v2.addNeighbor(new Edge(v4, 1)); v2.addNeighbor(new Edge(v5, 2)); v3.addNeighbor(new Edge(v1, 4)); v3.addNeighbor(new Edge(v4, 3)); v4.addNeighbor(new Edge(v5, 1)); graph.add(v0); graph.add(v1); graph.add(v2); graph.add(v3); graph.add(v4); graph.add(v5); ShortestPath algorithm = new ShortestPath(graph); algorithm.compute(); for(Vertex v: graph){ System.out.println("Distance from s: " + v.getMinDistance() + " - " + v.getPredecessor()); } } }
import java.util.List;
import java.util.ArrayList;
import java.util.Stack;

public class App {
    public static void main(String args[]){
        List<Vertex> graph = new ArrayList();

        Vertex v0 = new Vertex("S");
        Vertex v1 = new Vertex("A");
        Vertex v2 = new Vertex("B");
        Vertex v3 = new Vertex("C");
        Vertex v4 = new Vertex("D");
        Vertex v5 = new Vertex("E");

        v0.addNeighbor(new Edge(v1, 1));
        v0.addNeighbor(new Edge(v3, 2));
        v1.addNeighbor(new Edge(v2, 6));
        v2.addNeighbor(new Edge(v4, 1));
        v2.addNeighbor(new Edge(v5, 2));
        v3.addNeighbor(new Edge(v1, 4));
        v3.addNeighbor(new Edge(v4, 3));
        v4.addNeighbor(new Edge(v5, 1));

        graph.add(v0);
        graph.add(v1);
        graph.add(v2);
        graph.add(v3);
        graph.add(v4);
        graph.add(v5);

        ShortestPath algorithm = new ShortestPath(graph);
        algorithm.compute();

        for(Vertex v: graph){
            System.out.println("Distance from s: " + v.getMinDistance() + " - " + v.getPredecessor());
        }
    }
}

Output

Distance from s: 0 - null
Distance from s: 1 - Vertex{name='S', predecessor=null}
Distance from s: 7 - Vertex{name='A', predecessor=Vertex{name='S', predecessor=null}}
Distance from s: 2 - Vertex{name='S', predecessor=null}
Distance from s: 5 - Vertex{name='C', predecessor=Vertex{name='S', predecessor=null}}
Distance from s: 6 - Vertex{name='D', predecessor=Vertex{name='C', predecessor=Vertex{name='S', predecessor=null}}}