• 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

  • 相关阅读:
    *VC编程规范
    C++的va_start() va_end()函数应用(转)
    * C++类的分解,抽象类与纯虚函数的需要性
    *C++中的回调
    *C++中使用接口
    C++模版使用
    *获取mac地址的方法
    *数字——字符之间的转换(转)
    eclipse雕虫小技一:eclipse打开文件目录
    Hibernate升级后注解方式的对象关系映射
  • 原文地址:https://www.cnblogs.com/DevinZ/p/4411436.html
Copyright © 2020-2023  润新知