Dijkstra模板(java)
阿新 • • 發佈:2018-11-12
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;
}
}
}