一.原理介绍:
首先把起点距离最近的点存下来,然后进行松弛(即找到距离起点最短的那个点),然后对之后的点重复此类操作,直到找到终点即可。下面我用图来演示一遍:
注:(d数组表示到某个点的距离)
首先,d[1]=0,因为起点到起点的距离为0,然后起点衍生的两个点为 2 和 3,1到2距离为1,所以d[2]=1,同理,d[3]=1,之后,2 和 3 均衍生了2个点,因此,d[4]=d[2]+2,d[5]=d[2]+2, d[6]=d[3]+3, d[7]=d[3]+3;之后到终点了,这里有些不同,因为到8的点有4个,我们需要一个一个进行比较,算出最近的点,通过计算,我们得出最近的点为 4,因为d[4]=3,d[8]=d[4]+1 d[8]=4,所以到8的最短路为四。
二:题目展示:
三:代码展示:
#include<bits/stdc++.h>
using namespace std;
const int N= 510;
int g[N][N],d[N];//g数组存的是点与点的距离,d则是到某点的距离。
bool str[N];
int n,m;
int dijkstra()
{
memset(d,0x3f,sizeof d);//初始化d为无穷大。
d[1]=0;//起点的距离
for(int i=0;i<n;i++)
{
int t=-1;
for(int j=1;j<=n;j++)
{
if(!str[j]&&(t==-1||d[t]>d[j]))//寻找最短的2个点。
t=j;
if(t==n)break;
}
str[t]=true;
for(int i=1;i<=n;i++)
{
d[i]=min(d[i],d[t]+g[t][i]);//比较到某点的路径,看哪条最短。
}
}
if(d[n]==0x3f3f3f3f)return -1;//如果到不了第n点,那么d[n]=无穷,返回-1
return d[n];
}
int main()
{
cin>>n>>m;
memset(g,0x3f,sizeof g);//同d数组的操作
while(m--)
{
int a,b,c;
cin>>a>>b>>c;
g[a][b]=min(g[a][b],c);//a到b的距离为c。
}
cout<<dijkstra()<<endl;
}
四:总结:
在提一嘴,如果有多条路到某一点,那么保留最短的那一条便可以了,因为,到终点的距离都是所以最短路组成的。另外,这个算法不能算带有负权边的最短路,可能会算错,因为dijksta更新时是更新未更新的点,已更新点到其他点的距离不会再进行更新了,导致有负数的那条边不会保留,而是会跳过。