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:

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

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

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

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

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

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}}}