鉴于之前我看到过非常好的博客,如果自己总结的话,大多也是按照别的博主的思路来解释,所以就直接推荐给大家这些优秀的博客;
Dijkstra:最短路径dijkstra算法精品代码(超详解)
Floyd:Floyd 算法最短路径问题精品(超详解)
关于代码模板,我还是想展示自己的模板,毕竟自己的用着才是最舒服的(其实都大同小异,自己写一遍才能成为自己的东西)
Dijkstra模板:
#include <bits/stdc++.h>
using namespace std;
const int maxx=1e3+7;
#define INF 0x3f3f3f3f
int dist[maxx];
int c[maxx][maxx];
int s[maxx];
int v,e,n,m;
void init()
{
memset(dist,INF,sizeof dist);//源点到所有点的最短距离初始为无穷大
memset(c,INF,sizeof c);
memset(s,0,sizeof s);
}
void dijkstra()
{
for(int i=1;i<=n;i++) dist[i]=c[v][i];//找到与源点直接相连接的点,并且更新dist
dist[v]=0;//源点到自己本身距离为0
s[v]=1;//首先把源点标记
for(int i=2;i<=n;i++)
{
int temp=INF;
int u=v;
for(int j=1;j<=n;j++)//找到与源点直接相连,并且距离最小的点
{
if(!s[j]&&dist[j]<temp)
{
u=j;
temp=dist[j];
}
}
s[u]=1;//将这个点标记(证明以后可以使用这个点作为中间点了)
for(int j=1;j<=n;j++)
{
if(!s[j]&&c[u][j]<INF)//然后从u的周围找到一个直接相连并且没有使用过的点
{
int newdist=dist[u]+c[u][j];//然后判断使用这个点是否能使距离变小,是的话就更新
if(newdist<dist[j])
dist[j]=newdist;
}
}
}
}
int main()
{
while(scanf("%d %d",&n,&m)&&n&&m)
{
init();//初始化数组;
int x,y,t;
for(int i=1;i<=m;i++)
cin>>x>>y>>t,c[x][y]=t,c[y][x]=t;//存图
v=1,e=n;
dijkstra();
cout <<dist[n]<<endl;
}
return 0;
}
带路径输出的Dijkstra
最短路径(dijkstra)以及输出路径
.
.
.
Floyd模板:
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
#define INF 0x3f3f3f3f
const int maxx=1e3+7;
int G[maxx][maxx];//存图数组
int path[maxx][maxx];//path[i][j]记录从i到j经过了那个点过来的
int n,m;//分别表示定点个数和边的个数
void init()
{
memset(G,INF,sizeof G);//初始化数组
memset(path,-1,sizeof path);
for(int i=0;i<maxx;i++)//到自己的距离为0
G[i][i]=0;
}
void Floyd()
{ //三重循环
for(int k=1;k<=n;k++){ //选中的中间值
for(int i=1;i<=n;i++){ //数组横坐标
for(int j=1;j<=n;j++){ //数组纵坐标
if(G[i][j]>G[i][k]+G[k][j]){ //如果以k中间点为中间点检测到路径更短
G[i][j]=G[i][k]+G[k][j]; //更新路径值
path[i][j]=k; //更新要经过的中间点
}
}
}
}
}
int main()
{
while(scanf("%d %d",&n,&m)&&n&&m)
{
init();//初始化
int x,y,z;
for(int i=0;i<m;i++)
{
scanf("%d %d %d",&x,&y,&z);
G[x][y]=z,G[y][x]=z;
}
Floyd();
printf("%d\n",G[1][n]);//输出点1到点n的最短距离
}
return 0;
}
.
带路径输出的Floyd只需要添加一个自己写的函数即可:
void ptf(int u,int v)
{
cout <<u<<"->";
while(path[u][v]!=-1)
{
u=path[u][v];
cout <<u<<"->";
}
cout <<v<<endl;
}
.
.
.
Dijkstra算法和Floyd算法的区别之处:
总结来说就是
1.
Dijkstra不能处理负权图,Flyod能处理负权图;
2.
Dijkstra处理单源最短路径
Flyod是处理多源最短路径
这个区别有个博主写的特别好,生动又形象,来吧!传送门:最短路径——Dijkstra算法和Floyd算法
3.
Dijkstra时间复杂度为O(n^2)
Flyod时间复杂度为O(n^3) 空间复杂度为O(n ^ 2);
所以题目中如果是单源点正权图,就用Dijkstra
如果是任意两个点之间的最短路径或者是负权图,就用Floyd;