dijkstra(迪杰斯特拉算法)

该算法按从源点到其它个点的最短路长度递增的顺序,依次确定源点到每个点的最短路。要求图中不能有负权的边。

Java实现的代码如下:

import java.util.*;
 
public class Main {
	/*
	 * 默认源点为0
	 */
	static Scanner sc=new Scanner(System.in);
	static int n,m;//顶点的个数,边的个数
	static long[][] g;//图的邻接矩阵
	static int[] prior;//前驱
	static long[] d;//最短路的距离
	static boolean[] s;//已确定的点的集合
	static int INF=Integer.MAX_VALUE;
	
	static void gInitialize(){//有向图的初始化
		n=sc.nextInt();
		m=sc.nextInt();
		g=new long[n][n];
		for(int i=0;i<g.length;i++)
			for(int j=0;j<g[i].length;j++)
				g[i][j]=INF;
		for(int i=0;i<m;i++)
			g[sc.nextInt()][sc.nextInt()]=sc.nextInt();
	}
	
	static void dijkstra(){
		prior=new int[n];
		d=new long[n];
		s=new boolean[n];
		for(int i=0;i<n;i++){
			d[i]=g[0][i];
		}
		s[0]=true;
		d[0]=0;
		while(true){//此循环体仅用来限制计算次数,每次确定一个顶点
			int v=-1;//中间点
			for(int i=0;i<n;i++){//从尚未使用过的顶点中选择一个距离最小的顶点,作为中间点
				if(!s[i]&&(v==-1||d[i]<d[v])){
					v=i;
				}
			}
			if(v==-1)//已经没有可以确定的顶点,算法结束
				break;
			s[v]=true;
			for(int i=0;i<n;i++){//用该中间点更新d
				if(!s[i]&&(d[v]+g[v][i]<d[i])){
					d[i]=d[v]+g[v][i];//更新
					prior[i]=v;//更改前驱为v
				}
			}
		}
	}
	
	public static void main(String[] args){
		gInitialize();
		dijkstra();
		System.out.println(d[sc.nextInt()]);//输出源点到一个指定终点的最短路距离
	}
}

1、算法正确性的简单证明:

在最开始时,只有起点的最短距离是确定的。而在尚未使用过的顶点中,距离d[i]最小的顶点就是最短距离已经确定的顶点。这是因为由于不存在负边,所以d[i]不会在之后的更新中变小。

2、时间复杂度:

邻接矩阵 O(n^2)
邻接表 O(n^2)
邻接表+binary heap O((n+m)logn)
邻接表+fibonacci heap O(m+nlogn)                                                                                                                                            priority_queue  O(mlogn)

3、该算法得到的最短路径生成树是最小生成树吗?

不一定,很少情况下是。这是由两个算法最后的循环体内的松弛操作的不同决定的(更新d或mincost)。简单来说,Dijkstra的松弛操作加上了到源点的距离,而Prim只考虑相邻节点的权值

当然也可以通过反例来证明:

设1为源点,则最短路径生成树的权值和为7,最小生成树的权值和为6,显然不同。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值