1. 程式人生 > >Dijkstra模板(java)

Dijkstra模板(java)

Dijkstra模板

  • 再求單源最短路徑時候,經常會用到Dijkstra演算法,在某些資料量小的情況下bfs或者dfs或許可以得到結果,但是一旦結果大的時候常規搜尋就很難在規定時間內得到答案。
  • Dijkstra基本思想:== 貪心==。Dijkstra其實就是一個在圖論中的貪心演算法。不過貪心的維度就是在預選點中的最短路徑
  • Dijkstra演算法的常規處理流程:
    1:首先,Dijkstra處理的是帶正權值的有向圖,那麼,就需要一個二維陣列(如果空間大用list陣列)儲存各個點到達的權值大小。
    2:其次,還需要一個boolean陣列判斷那些點已經確定,int陣列記錄長度。那些點沒有確定。每次確定的點需要標記,如果遇到已經確定的點就不該拋入佇列進行比較。
    3:需要優先佇列拋入已經確定點的周圍點。每次丟擲確定最短路徑的那個並且確定,直到所有點確定為止。
  • 簡單的概括流程為:
    一:一般從選定點開始拋入優先佇列。(路徑一般為0),boolean標記0的位置,然後0周圍的點拋入優先佇列中(可能是node類),第一次就結束了
    二:從佇列中丟擲距離最近的那個點(目前是0周圍鄰居)這個點一定是最近的(所有權值都是正的,點的距離只能越來越長。)標記這個點為true,並且將這個點的鄰居加入佇列,那麼下次點一定在這個點的鄰居和以前的點中產生。並且我們只能確定這個佇列中只有一個最近點,因為有可能第二最近的就是被確定點的鄰居。所以每次只能確定一個點,知道確定所有點。
    三:重複二的操作,直到所有點都確定。
    程式碼為:
import java.io.BufferedReader;
import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.io.StreamTokenizer; import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.PriorityQueue; import java.util.Queue; import
java.util.Scanner; //n 個定點 m條邊的圖 public class Main{ static int leng[]; public static void main(String[] args) throws IOException { // TODO 自動生成的方法存根 StreamTokenizer in=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in))); PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out)); in.nextToken(); int n=(int)in.nval;in.nextToken();int m=(int)in.nval; int map[][]=new int[n][n]; boolean bool[][]=new boolean[n][n]; List<Integer>list[]=new ArrayList[n]; for(int i=0;i<n;i++) { list[i]=new ArrayList<>(); } leng=new int[n];//記錄長度 boolean jud[]=new boolean[n]; for(int i=1;i<n;i++) {leng[i]=Integer.MAX_VALUE;} for(int i=0;i<m;i++) { in.nextToken();int u=(int)in.nval; in.nextToken();int v=(int)in.nval; in.nextToken();int l=(int)in.nval; map[u-1][v-1]=l; list[u-1].add(v-1); bool[u-1][v-1]=true;//兩點聯通 } Queue<Integer>q1=new PriorityQueue<>(compare); q1.add(0); int count=0; while(!q1.isEmpty()) { int x=q1.poll(); if(count>=n) {break;}//所有點都確定 if(!jud[x]) { jud[x]=true;count++; for(int i=0;i<list[x].size();i++)//遍歷 { if(bool[x][list[x].get(i)]&&!jud[list[x].get(i)])//有路徑並且未被確定 { if(leng[list[x].get(i)]==Integer.MAX_VALUE) //第一次加入,更新路徑 {leng[list[x].get(i)]=leng[x]+map[x][list[x].get(i)];q1.add(list[x].get(i));} else if(leng[list[x].get(i)]>leng[x]+map[x][list[x].get(i)]) { leng[list[x].get(i)]=leng[x]+map[x][list[x].get(i)]; } //System.out.println( no.leng+map[no.x][i]); } } } } for(int i=1;i<n;i++)//依次輸出最近點 { out.println(leng[i]); } out.flush(); } static Comparator<Integer>compare=new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { return leng[o1]-leng[o2]; } }; static class node { int x;int leng; public node(int x,int leng) { this.x=x; this.leng=leng; } } }