Single-Source Shortest Paths

 

1. Dijkstra's Algorithm

  Dijkstra's Algorithm is widely used to determine the single-source shortest path in a weighted graph whose weights are all non-negative. Here is my solution to a problem from SJTU ACM Online Judge, in which I used this algorithm to determine the shortest path between two specific vertices:

  1 import java.util.*;
  2 
  3 class AdjList {
  4     private class Vert {
  5         public Edge next;
  6     }
  7     private class Edge {
  8         public int end, weight; 
  9         public Edge next;
 10         
 11         public Edge(int end,int weight,Edge next) {
 12             this.end = end;
 13             this.weight = weight;
 14             this.next = next;
 15         }
 16     }
 17     private class HeapItem {
 18         public int idx, dist;
 19         
 20         public HeapItem(int idx,int dist) {
 21             this.idx = idx;
 22             this.dist = dist;
 23         }
 24         public int index() {
 25             return idx;
 26         }
 27     }
 28     
 29     private final int INF = 1000001;
 30     private int num;
 31     private Vert [] vert;
 32 
 33     public AdjList(int num) {
 34         this.num = num;
 35         vert = new Vert[num];
 36         for (int i=0;i<num;i++) {
 37             vert[i] = new Vert();
 38         }
 39     }
 40     public void insert(int i,int j,int w) {
 41         vert[i].next = new Edge(j,w,vert[i].next);
 42     }
 43     private void printPath(int [] prev,int pos) {
 44         if (prev[pos]<0) {
 45             System.out.print(pos+1);
 46         } else {
 47             printPath(prev,prev[pos]);
 48             System.out.print(" "+(pos+1));
 49         }
 50     }
 51     public void shortPath(int p,int r) {
 52         PriorityQueue<HeapItem> q = new PriorityQueue<HeapItem>(10000,
 53                 new Comparator<HeapItem>() {
 54                     public int compare(HeapItem a,HeapItem b) {
 55                         if (a.dist<b.dist) {
 56                             return -1;
 57                         } else if (a.dist>b.dist) {
 58                             return 1;
 59                         } else  {
 60                             return 0;
 61                         }
 62                     }
 63                 }
 64         );
 65         boolean [] vis = new boolean[num];
 66         int [] dist = new int [num];
 67         int [] cnt = new int [num];
 68         int [] prev = new int [num];
 69         // initialize single source:
 70         for (int i=0;i<num;i++) {
 71             dist[i] = cnt[i] = INF;
 72         }
 73         dist[p] = 0;
 74         cnt[p] = 0;
 75         prev[p] = -1;
 76         q.add(new HeapItem(p,0));
 77         int pos = -1;
 78         while (!q.isEmpty()) {
 79             do {
 80                 pos = q.poll().index();
 81             } while (vis[pos]);
 82             vis[pos] = true;
 83             if (pos==r) {
 84                 break;
 85             }
 86             Edge itr = vert[pos].next;
 87             while (itr!=null) {
 88                 // do relaxation for each vertex adjacent to vert[pos]
 89                 if (!vis[itr.end] && dist[itr.end]>dist[pos]+itr.weight) {
 90                     dist[itr.end] = dist[pos]+itr.weight;
 91                     cnt[itr.end] = cnt[pos]+1;
 92                     prev[itr.end] = pos;
 93                     q.add(new HeapItem(itr.end,dist[itr.end]));
 94                 } else if (!vis[itr.end]&&dist[itr.end]==dist[pos]+itr.weight&&cnt[itr.end]>cnt[pos]+1) {
 95                     cnt[itr.end] = cnt[pos]+1;
 96                     prev[itr.end] = pos;
 97                 }
 98                 itr = itr.next;
 99             }
100         }
101         System.out.println(dist[r]);
102         printPath(prev,r);
103         System.out.println();
104     }
105 }
106 
107 public class Main {
108     public static void main(String[] args) {
109         Scanner in = new Scanner(System.in);
110         int v = in.nextInt();
111         int e = in.nextInt();
112         int p = in.nextInt()-1;
113         int r = in.nextInt()-1;
114         AdjList g = new AdjList(v);
115         for (int i=0;i<e;i++) {
116             int j = in.nextInt()-1;
117             int k = in.nextInt()-1;
118             int w = in.nextInt();
119             g.insert(j,k,w);
120         }
121         in.close();
122         g.shortPath(p,r);
123     }
124 }

 

2. Bellman-Ford Algorithm

  This is an algorithm that can determine the single-source shortest paths in a weighted graph even if the graph has negative weights. I used it to solve a problem from SJTU ACM Online Judge:

 1 import java.util.*;
 2 
 3 class AdjList {
 4     private static class Vert {
 5         public Vert next;
 6         public int weight,end;
 7     }
 8     
 9     private final int INF = 10000000;
10     private int num;
11     private Vert[] vert;
12     
13     public AdjList(int num) {
14         this.num = num;
15         vert = new Vert[num];
16         for (int i=0;i<num;i++) {
17             vert[i] = new Vert();
18         }
19     }
20     public void insEdge(int p,int r,int w) {
21         Vert v = new Vert();
22         v.next = vert[p].next;
23         v.weight = w;
24         v.end = r;
25         vert[p].next = v;
26     }
27     public int shortPath(int src,int dest) {
28         // Bellman-Ford Algorithm:
29         // Precondition: no negative-weight cycles exist
30         // Postcondition: return the shortest distance
31         //            between vert[src] and vert[dest]
32         int[] dist = new int[num];
33         for (int i=0;i<num;i++) {
34             dist[i] = INF;
35         }
36         dist[src] = 0;
37         for (int i=1;i<num;i++) {
38             // for each vertices do relaxation (num-1) times
39             for (int j=0;j<num;j++) {
40                 Vert itr = vert[j].next;
41                 while (itr!=null) {
42                     relax(j,itr,dist);
43                     itr = itr.next;
44                 }
45             }
46         }
47         return dist[dest];
48     }
49     private boolean relax(int i,Vert v,int[] dist) {
50         if (dist[i]+v.weight<dist[v.end]) {
51             dist[v.end] = dist[i]+v.weight;
52             return true;
53         } else {
54             return false;
55         }
56     }
57 }
58 
59 public class Main {
60     public static Scanner in;
61     
62     public static void main(String[] args) {
63         in = new Scanner(System.in);
64         AdjList g = new AdjList(in.nextInt());
65         int m = in.nextInt();
66         int s = in.nextInt()-1;
67         int d = in.nextInt()-1;
68         for (int i=0;i<m;i++) {
69             int p = in.nextInt()-1;
70             int r = in.nextInt()-1;
71             int w = in.nextInt();
72             g.insEdge(p,r,w);
73         }
74         in.close();
75         System.out.println(g.shortPath(s,d));
76     }
77 }

 

3. SPFA Algorithm

  For the problem above, we can have a more efficient solution if we draw on another algorithm called SPFA (Shortest Path Faster Algorithm):

 1 import java.util.*;
 2 
 3 class AdjList {
 4     private class Vert {
 5         public Edge next;
 6     }
 7     private class Edge {
 8         public int end, weight;
 9         public Edge next;
10         
11         public Edge(int end,int weight,Edge next) {
12             this.end = end;
13             this.weight = weight;
14             this.next = next;
15         }
16     }
17     
18     public final int INF = 1000001;
19     private int num;
20     private Vert [] vert;
21     
22     public AdjList(int num) {
23         this.num = num;
24         vert = new Vert[num];
25         for (int i=0;i<num;i++) {
26             vert[i] = new Vert();
27         }
28     }
29     public void insEdge(int i,int j,int w) {
30         vert[i].next = new Edge(j,w,vert[i].next);
31     }
32     public int shortPath(int p,int r) {
33         Queue<Integer> q = new LinkedList<Integer>();
34         int [] dist = new int[num];
35         for (int i=0;i<num;i++) {
36             dist[i] = INF;
37         }
38         dist[p] = 0;
39         q.add(new Integer(p));
40         while (!q.isEmpty()) {
41             int pos = q.poll().intValue();
42             Edge itr = vert[pos].next;
43             while (itr!=null) {
44                 // do relaxation for each vertex adjacent to vert[pos]
45                 if (dist[itr.end]>dist[pos]+itr.weight) {
46                     dist[itr.end] = dist[pos]+itr.weight;
47                     q.add(new Integer(itr.end));
48                 }
49                 itr = itr.next;
50             }
51         }
52         return dist[r];
53     }
54     private void printPath(int [] prev,int pos) {
55         if (prev[pos]<0) {
56             System.out.print(pos+1);
57         } else {
58             printPath(prev,prev[pos]);
59             System.out.print(" "+(pos+1));
60         }
61     }
62 }
63 
64 public class Main {
65     public static void main(String[] args) {
66         Scanner in = new Scanner(System.in);
67         int v = in.nextInt();
68         int e = in.nextInt();
69         int p = in.nextInt()-1;
70         int r = in.nextInt()-1;
71         AdjList g = new AdjList(v);
72         for (int i=0;i<e;i++) {
73             int j = in.nextInt()-1;
74             int k = in.nextInt()-1;
75             int w = in.nextInt();
76             g.insEdge(j,k,w);
77         }
78         in.close();
79         System.out.println(g.shortPath(p, r));
80     }
81 }

 

 

References:

      1. Cormen, T. H. et al. Introduction to Algorithms [M] .  北京:机械工业出版社, 2006-09

posted on 2015-04-03 18:39  DevinZ  阅读(357)  评论(0编辑  收藏  举报

导航