Floyd和Dijkstra的最短路问题
这两个算法都是用来求最短路径的算法,主要区别就是Floyd求的是任意两点之间的最短路值,Dijkstra主要求得是单源最短路,就是一个点到其他点的最短路值,二者都不能解决负权值问题。
弗洛伊德算法(Floyd算法)主要是用了一种“松弛”的方法,就是在从a到b的路线中是否能够找到一个中转点,比如说k点,就是dis[a][k]+dis[k][b]的值小于dis[a][b]的时候,可以从a出发先到k点,再转到b点,这样就可以达到题中最短的目的,然后以此类推。将已知所有点都作为中转点,进行一轮轮的比较。核心代码就只有5行,比较简单暴力。
for(k=1;k<=n;k++)//最外层的循环表示中转点的更新
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(e[i][j]>e[i][k]+e[k][j])//这里有一个稍难理解的一点,
//就是e[i][k],e[k][j]是经过之前几次中转后得到的最优解,所以可以中转几次的情况
e[i][j]=e[i][k]+e[k][j];
迪杰斯特拉算法(Dijkstra算法)是求单源最短路的一个算法,核心代码也不多,主要一个思想就是找到确定的最短距离的点,然后对其他点进行松弛的处理,标记已知是最短距离的点,然后根据点的数量确定循环结束。
#include <stdio.h>
#include <string.h>
int e[10010][10010];
int dis[10010],book[10010];
int inf=99999999;
int main()
{
int a,b,c,n,m;
int i,j,k,u,s,min;
while(scanf("%d%d",&n,&m)!=EOF)
{
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{
if(i==j)
e[i][j]=0;
else
e[i][j]=inf;
}
for(i=1;i<=m;i++)
{
scanf("%d%d%d",&a,&b,&c);
if(c<e[a][b])//从一个地点到另外一个地点的路可能不止一条,只保存最短的一条这里有时候会坑
e[a][b]=c;
}
memset(dis,0,sizeof(dis));
memset(book,0,sizeof(book));
for(i=1;i<=n;i++)
dis[i]=e[1][i];//这里的源点是1点
book[1]=1;
for(s=1;s<n;s++)//循环n-1次,将除源点之外的n-1个点找出来
{
min=inf;//寻找距源点最近的未标记的点
for(i=1;i<=n;i++)
if(book[i]==0&&dis[i]<min)
{
min=dis[i];
u=i;
}
book[u]=1;
for(k=1;k<=n;k++)//从确定距离源点最近的已知点出发,对每个点进行比较
{
if(e[u][k]<inf)//确认两点之间是存在路径的
{
if(dis[k]>dis[u]+e[u][k])
dis[k]=dis[u]+e[u][k];
}
}
}
for(i=1;i<=n;i++)
printf("%d ",dis[i]);
}
return 0;
}