最短路算法(Dijkstra朴素版)

26 篇文章 1 订阅
8 篇文章 0 订阅

个人理解:这个求单源最短路的方法和Prim算法求最小生成树非常相似,都是从未加入顶点

中找出一个顶点权值最小的,然后加进顶点集当中,唯一不同的是Prim更新的是新加入点与

其他点的最小权值,而Dijkstra是更新源点到该点总权值(或者说是进行一轮松弛)。


再次copy下维基百科:

算法描述

这个算法是通过为每个顶点 v 保留目前为止所找到的从s到v的最短路径来工作的。初始时,原点 s 的路径长度值被赋为 0 (d[s] = 0),若存在能直接到达的边(s,m),则把d[m]设为w(s,m),同时把所有其他(s不能直接到达的)顶点的路径长度设为无穷大,即表示我们不知道任何通向这些顶点的路径(对于 V 中所有顶点 v除 s 和上述 m 外 d[v] = ∞)。当算法退出时,d[v] 中存储的便是从 s 到 v 的最短路径,或者如果路径不存在的话是无穷大。 Dijkstra 算法的基础操作是边的拓展:如果存在一条从 u 到 v 的边,那么从 s 到 v 的最短路径可以通过将边(uv)添加到尾部来拓展一条从 s 到 u 的路径。这条路径的长度是 d[u] + w(u, v)。如果这个值比目前已知的 d[v] 的值要小,我们可以用新值来替代当前 d[v] 中的值。拓展边的操作一直运行到所有的 d[v] 都代表从 s 到 v 最短路径的花费。这个算法经过组织因而当 d[u] 达到它最终的值的时候每条边(uv)都只被拓展一次。

HDU 2544

可以用来测试代码正确与否;

#include<stdio.h>
#include<string.h>

int graph[110][110],dis[110];

const int inf=0xfffff;

void initi(int n)
{
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			graph[i][j]=inf;
	for(int i=1;i<=n;i++)
		dis[i]=inf;
	dis[1]=0;
}

void  Dijkstra(int n)
{
	int minLoc,i,j,vis[110];
	memset(vis,0,sizeof(vis));
	vis[1]=1;
	for(i=2;i<=n;i++)
		dis[i]=graph[1][i];
	for(i=2;i<=n;i++)
	{
		int min=inf;
		for(j=2;j<=n;j++)
		{
			if(!vis[j]&&dis[j]<min)//寻找未加入顶点中与已加入顶点中的最小总权值 
			{
				min=dis[j];
				minLoc=j;
			}
		}
		vis[minLoc]=1;
		for(j=2;j<=n;j++)//对新加入顶点进行一轮松弛 
			if(!vis[j]&&dis[minLoc]+graph[minLoc][j]<dis[j])
				dis[j]=dis[minLoc]+graph[minLoc][j];			
	}
}

int main()
{
	int i,j,n,m;
	while(scanf("%d%d",&n,&m))
	{
		int a,b,c;
		if(n==0&&m==0)
			break;
		initi(n);
		for(i=0;i<m;i++)
		{
			scanf("%d%d%d",&a,&b,&c);
			graph[a][b]=graph[b][a]=c;
		}
	 	Dijkstra(n);
	 	printf("%d\n",dis[n]);
	}
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值