zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    target runtime apache v6.0 not defined解决
    java.lang.AbstractMethodError: javax.servlet.jsp.JspFactory.getJspApplicationContext(Ljavax/servlet/ServletContext;)Ljavax/servlet/jsp/JspApplicationContext;
    The valid characters are defined in RFC 7230 and RFC 3986问题
    invalid END header解决方法
    You have more than one version of ‘org.apache.commons.logging.Log’ visible, which is not allowed问题解决
    Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986
    在eclipse中import java web项目时遇到的一些问题并将该项目通过tomcat发布
    java byte转string 涉及到字节流中有中文
    spring+mybatis框架搭建时遇到Mapped Statements collection does not contain value for...的错误
    试试看读一下Zepto源码
  • 原文地址:https://www.cnblogs.com/DevinZ/p/4411436.html
Copyright © 2011-2022 走看看