图论算法----最短路径Floyed算法和Dijkstra算法详解

来源:互联网 发布:单片机数字电压表 编辑:程序博客网 时间:2024/05/16 11:28

一、题目描述

最短路径问题(floyed.cpp & dijkstra.cpp)

题目描述
平面上有n个点(n<=100),每个点的坐标均在-10000~10000之间。其中的一些点之间有连线。若有连线,则表示可从一个点到达另一个点,即两点间有通路,通路的距离为两点间的直线距离。现在的任务是找出从一点到另一点之间的最短路径。

输入
第1行:1个整数n
第2..n+1行:每行2个整数x和y,描述了一个点的坐标
第n+2行:1个整数m,表示图中连线的数量
接下来有m行,每行2个整数i和j,表示第i个点和第j个点之间有连线
最后1行:2个整数s和t,分别表示源点和目标点

输出
第1行:1个浮点数,表示从s到t的最短路径长度,保留2位小数

样例输入
5
0 0
2 0
2 2
0 2
3 1
5
1 2
1 3
1 4
2 5
3 5
1 5

样例输出
3.41


二、分析

1、Floyed算法O(n³)
我们先对输入的数据进行初始化:
<span style="font-size:18px;">#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>using namespace std;double dis[105][105];//dis[i][j]表示点i到点j的最短路径长度int zb[105][2];//坐标int main(){//freopen("floyed.in","r",stdin);//freopen("floyed.out","w",stdout);int n,m,i,j,k,x,y,q,z;scanf("%d",&n);for(i=1;i<=n;i++)scanf("%d%d",&zb[i][0],&zb[i][1]);scanf("%d",&m);memset(dis,0x7f,sizeof(dis));//清为最大值,以便后面求最短路for(i=1;i<=m;i++){scanf("%d%d",&x,&y);dis[x][y]=sqrt(pow(1.0*(zb[x][0]-zb[y][0]),2)+pow(1.0*(zb[x][1]-zb[y][1]),2));//计算两点之间的距离dis[y][x]=dis[x][y];}scanf("%d%d",&q,&z);}</span>
floyed算法其实就是3个for循环,用i、j、k三个循环变量来枚举每一个点。用k来枚举中转点,i、j来枚举i到j的点。

如果dis[i][k]+dis[k][j]<dis[i][j],则dis[i][j]=dis[i][k]+dis[k][j]。就是 i 到 k 的距离与 k 到 j 的距离的和,小于 i 到 j 的距离,就把dis[i][j]变成 i 到 k 的距离与 k 到 j 的距离
和。
<span style="font-size:18px;">for(k=1;k<=n;k++)for(i=1;i<=n;i++)for(j=1;j<=n;j++)if(i!=j&&j!=k&&i!=k)dis[i][j]=min(dis[i][k]+dis[k][j],dis[i][j]);</span>
最后输出结果:
<span style="font-size:18px;">printf("%.2f",dis[q][z]);</span>

2、Dijkstra算法O(n²)

还是先进行初始化:
<span style="font-size:18px;">#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>using namespace std;double f[105][105];//用f[x][y]来存x,y的距离(但不是最短距离)double dis[105];//存最终结果bool b[105];//判断重复int zb[105][2];int main(){//freopen("dijkstra.in","r",stdin);//freopen("dijkstra.out","w",stdout);int n,m,i,j,k,x,y,q,z,xi;scanf("%d",&n);for(i=1;i<=n;i++)scanf("%d%d",&zb[i][0],&zb[i][1]);scanf("%d",&m);memset(f,0x7f,sizeof(f));for(i=1;i<=m;i++){scanf("%d%d",&x,&y);f[x][y]=sqrt(pow(1.0*(zb[x][0]-zb[y][0]),2)+pow(1.0*(zb[x][1]-zb[y][1]),2));f[y][x]=f[x][y];}scanf("%d%d",&q,&z);}</span>
我们可以发现dis变成了一维数组,因为Dijkstra算法是一种用来计算一个点到其他所有点的最短路径算法,
Dijkstra算法是先用一个循环变量 i 来枚举所有点,把每一个枚举过的点在b数组中标记为1,然后记录下距离
点 i 最近的一个点 k ,以点 k 来进行其他最短距离的更新,
<span style="font-size:18px;">for(i=1;i<=n;i++)dis[i]=f[q][i];b[q]=1;dis[q]=0;for(i=1;i<=n-1;i++){xi=10000000;k=0;for(j=1;j<=n;j++){if(b[j]==0&&dis[j]<xi){xi=dis[j];k=j;}}if(k==0)break;b[k]=1;for(j=1;j<=n;j++)//进行更新dis[j]=min(dis[j],dis[k]+f[k][j]);}printf("%.2f",dis[z]);</span>





1 0
原创粉丝点击