复习了一下Dijkstra算法
迪杰斯特拉算法的基本思想就是:通过边来松弛源点到其他点的距离,每次找到离源点最近的一个点,通过这个点去更新源点到其他点的最短距离。
步骤:
下面称存储源点到其他点的最短距离的数组为dis[],vis[]存储已经确定为最短距离的点,edge[i][j]存储两点之间的距离
(1)初始化,源点到本身的最短路径为0,源点可直接到达的点的初始最短距离(注意了,是初始,因为后面还会进行松弛操作,所谓松弛操作就是通过其他点来缩短此点到源点的距离)为
(2)每次在dis中选择一个离源点最近的点,并标记,vis[x]=1,防止再次访问,若存在一条u->v的点且u非源点,如果发现dis[v]>dis[u]+edge[u][v],则更新源点到此点的距离
(3)不断重复第三步,直到所有点都访问过且更新完毕
看不懂可以看一下,下面的过程
通过上图来讲解一下整个算法的过程:
先建立一个存储源点到其他顶点最短路径的数组dis[n];
设源点为1,则dis[1]=0,dis[2]=1,dis[3]=12,因为点2和点3是源点可以直接到达的位置,其他点的距离都初始化为∞。整个数组为dis[0][1][12][∞][∞][∞];
初始化完毕,下面进入正戏:
由数组可知②是距离当前点最近的点,那么我们现在就从①->②,并标记2,表示已访问,在②中发现从②可以直接到达的点有③,④
那么我们就可以更新数组了,首先更新dis[4]=3,另外,我们发现dis[3]=12,而dis[2]+edge[2][3]=1+9=10>12,
更新dis[3]=10
模板:
#include<iostream>
#include<cstring>
#include<math.h>
#include<stdlib.h>
#include<cstring>
#include<cstdio>
#include<utility>
#include<algorithm>
#include<map>
using namespace std;
const int inf=0x3f3f3f3f;
int n,m;
int dis[5005],e[5005][5005],vis[5005];
void dijkstra(){
int min,u;
for(int k=1;k<=n-1;k++){
min=inf;
//寻找离源点最近的点
for(int i=1;i<=n;i++){
if(!vis[i]&&dis[i]<min){
min=dis[i];
u=i;
}
}
vis[u]=1;
//松弛操作
for(int i=1;i<=n;i++){
if(e[u][i]<inf){
dis[i]=max(dis[i],dis[u]+e[u][i]);
}
}
}
}
int main( )
{
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n>>m;
int a,b,c;
//初始化边
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++)
if(i==j)e[i][j]=0;
else e[i][j]=inf;
}
for(int i=1;i<=m;i++){//读入边
cin>>a>>b>>c;
e[a][b]=c;
}
//初始化dis
for(int i=1;i<=n;i++){
dis[i]=e[1][i];
}
vis[1]=1;
//dijkstra算法核心
dijkstra();
for(int i=1;i<=n;i++)cout<<dis[i]<<endl;
return 0;
}