迪杰斯特拉(Dijkstra)算法详解,通俗易懂

该算法可以解决单源最短路径问题

单源指:以图中一个点作为源点,该算法用来求该源点到其他各个点的最短路径,我们代码中用dst数组记录

基本思想:

         每次找到离源点最近的一个顶点u,然后再拿这个顶点u进行更新dst数组(即dst[k] = min(dst[k] , dst[u] + edge[u][k])),最终得到源点到其余所有点的最短路径

基本步骤:

一、把图中所有顶点分到俩个集合中,即最短路径的顶点集合S和未知最短路径的顶点集合Q。很显然初始时,只有源点在S集合中,其他顶点都在Q集合中。 在代码实现时,我们可以开一个bool型的数组mark,mark[i] = true表示i顶点在S集合中。mark[i] = false表示i顶点在Q集合中。

const int MAXN=1e5;

bool mark[MAXN];

memset(mark,0,sizeof mark); //除源点外,其他顶点在Q集合中
mark[1]=true;    //顶点1作为源点,初始在S集合中

           二、设置最短路径数组dst并不断更新:初始时:dst[i] = edge[s][i],(s为源点,edge为邻接矩阵)。dst[s] = 0, mark[s] = true.  此时在Q集合中选择一个离源点s最近的顶点u加入S集合中。

const int inf = 0x3f3f3f3f; //一个非常大的数,相当于无穷大
int u; //距离源点s最近的顶点u

int min_path = inf;

for(int j=1;j<=n;j++)
{
    if(mark[j] == 0 && dst[j] < min_path) //在集合Q中选择离源点s最近的顶点
    {
         min_path = dast[j];
         u = j;
    }
    mark[u] = true; //把找到的最近顶点u放到S集合中
}

然后拿新加入的顶点u进行更新dst数组,即在集合Q中找一个顶点k,如果原来顶点k到源点s的距离 > (顶点k到u的距离 + 顶点u到源点s的距离),那么更新 原来顶点k到源点s的距离 =  (顶点k到u的距离 + 顶点u到源点s的距离)

for(int k=1;k<=n;k++)
{
    if(edge[u][k]<inf && mark[k] == 0) // u可以到达k并且,k在集合Q中
    {
          if(dst[k] > dst[u] + edge[u][k]) //原来顶点k到源点s的距离 > (顶点u到源点s的距离 + u 
                                           //到k的距离)
          {
                dst[k] = dst[u] + edge[u][k]; 
                //顶点k到源点s的距离 = 源点s到顶点u的距离 + u到k的距离
          }
    }
}

        三、在集合Q中再新找一个离源点s最近的顶点u加入集合S中,重复上面操作,直到所有顶点都到集合S中。dst数组中就是源点s到其他各个顶点的最短路径

完整代码

const int inf=0x3f3f3f3f;
const int MAXN=1e3 + 1;
int edge[MAXN][MAXN]; 
bool mark[MAXN]; //标记顶点在哪个集合
int dst[MAXN];//最短路径数组
int s; //s代表源点
int u; //中间顶点u
fill(edge,edge + MAXN*MAXN,inf);//先初始化邻接矩阵,再输入

for(i = 1; i <= n; i++) dst[i] = edge[s][i]; //源点s到其他各个顶点距离的初始化
dst[s] = 0;
memset(mark,0,sizeof mark);
mark[s] = 1;
int min_path;
for(i = 1; i <= n-1; i++){  //初始源点已在集合S中,再放入n-1个顶点算法结束
	//找到离源点最近的顶点u,称它为新中心点
	min_path = inf;
	for(j = 1; j <= n; j++){
		if(mark[j] == 0 && dst[j] < min_path){
			min_path = dst[j];
			u = j;
		}
	}
	mark[u] = 1;
	//更新最短路径数组
	for(k = 1; k <= n; k++){
		if(edge[u][k] < inf && mark[k] == 0){
			if(dst[k] > dst[u] + edge[u][k])
				dst[k] = dst[u] + edge[u][k];			
		}
	}
}

  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值