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;
}
}
}