DIJKSTRA算法实现单源最短路
本人很懒并且很渣,所以写得不合适的地方还请各位大牛指出,
注:下面针对的图是无向图,并且采用邻接矩阵的方式存储图
先来说明下什么是最短路,从一个给定的顶点开始,到任意一个顶点的最短路径,就成为源点到该点的最短路径
算法原理:
按路径长度递增次序产生最短路径算法:
把V分成两组:
(1)S:已求出最短路径的顶点的集合
(2)V-S=T:尚未确定最短路径的顶点集合
将T中顶点按最短路径递增的次序加入到S中.
保证:
(1)从源点V0到S中各顶点的最短路径长度都不大于从V0到T中任何顶点的最短路径长度
(2)每个顶点对应一个距离值
S中顶点:从V0到此顶点的最短路径长度
T中顶点:从V0到此顶点的只包括S中顶点作中间顶点的最短路径长度
依据:可以证明V0到T中顶点Vk的最短路径,或是从V0到Vk的直接路径的权值;或是从V0经S中顶点到Vk的路径权值之和 。
好的,这不是我的风格,本段话摘自勇者王的博客。。。
接下来是我自己的理解:其实这个算法就是把图中所有的顶点分成两个几个s,v,起先s集合只有给定的源点,然后去寻找当前的最短路,把另个属于v集合的顶点加入到s集合,重复上述操作,知道s里包含所有的顶点、
来看一个例子 ,下图是一个普通的带权值的有向图,我们把顶点1作为源点,接下来去寻找最短路,先给出我的一张手绘稿
先把上面的三张图理解了
下面是代码实现
先说下使用的一些数据结构
int G[][], 矩阵,存放权值
int prev[],这个一维数组用来存放最短路上一个顶点的前一个顶点
int dist[],这个一维数组存放从源点出发到任意点的最短路
bool used[],标记数组,其实就是来判断顶点是否加入到集合s中
好的,有了这些基础,差不多可以码代码了,不过我们得定义一些宏
#define maxn 105 //最大顶点个数
#define mx 10000000 //表示两个点之间没有路径
PS:这个代码是我AC的一道杭电acm上的题的源码,比较水的,我加了下注释 题目链接http://acm.hdu.edu.cn/showproblem.php?pid=1874
#include<stdio.h>
#define maxn 105
#define mx 10000000
int G[maxn][maxn];
int prev[maxn],dist[maxn];
void Dijkstra(int n,int Source_v)
{
bool used[maxn]; //作用上面已经介绍过
int i ,j,k;
for(i=1;i<=n;i++)
{
used[i]=0; //初始化
dist[i]=G[Source_v][i];//那么一开始的最短路当然是直接由源顶点到目标顶点的权值的大小
if(dist[i]==mx)//如果说没有直接路径
prev[i]=0; //我们认为这个顶点的依附顶点(前一个顶点)为0
else
prev[i]=Source_v;//与源顶点直接相连 ,前一个顶点就是源顶点
}
used[Source_v]=1; //表示源顶点已经标记,已加入到集合s中
dist[Source_v]=0;//源顶点到源顶点距离为0
for(i=2;i<=n;i++)//寻找最短路 ,注意i是从2开始循环的,第一个顶点是源顶点
{
int u=Source_v;//存放一个存在当前最小权值边的顶点
int min=mx;
for(j=1;j<=n;j++) //此循环的目的是寻找到当前最小权值边
if(!used[j] && min>dist[j]) //满足条件:既没有加入到集合s中,也比当前最小值要更小
{
min=dist[j]; //更新
u=j;
}
used[u]=1;//显然要把这个顶点加进来,标记1
for(j=1;j<=n;j++) //更新
{
if(!used[j] && G[u][j] < mx)//加入从u到j有路径
{
int newdist=G[u][j]+dist[u];//松弛操作
if(newdist<dist[j])//判断Soure_v到j的路径和Source_v到u再到j的路径大小
{
dist[j]=newdist;
prev[j]=u;
}
}
}
}
}
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m))
{
int i,j,a,b,c,s,t;
for(i=0;i<=n;i++)
for(j=0;j<=n;j++)
{
G[i][j]=mx;
G[j][i]=mx;//这样表示无向图
}
for(i=1;i<=m;i++)
{
scanf("%d%d%d",&a,&b,&c);
if(c<G[a+1][b+1]) //防止重边
{
G[a+1][b+1]=c;
G[b+1][a+1]=c;
}
}
scanf("%d%d",&s,&t);
s+=1;
t+=1;
Dijkstra(n,s);
if(dist[t]!=mx)
printf("%d\n",dist[t]);
else
printf("-1\n");
}
return 0;
}