图的最短路径:Dijkstra 和 Floyd
2024-08-28 08:44:17
//最短路径
/* dijkstra
Dijkstra(迪杰斯特拉)算法的核心思想是贪心策略+动态规划
http://www.programgo.com/article/4721147659/
Dijkstra算法能得出最短路径的最优解,但是效率低
*/
Floyed 算法:
Floyed算法比较简单,其思想可以参照三角形的特性中,两边和与第三边的关系,a 和 b的最短路径要么是(a,b)要么是(a,c,b),这取决于 a->b和a->c->b的大小。
算法思想原理:
Floyd算法是一个经典的动态规划算法。用通俗的语言来描述的话,首先我们的目标是寻找从点i到点j的最短路径。从动态规划的角度看问题,我们需要为这个目标重新做一个诠释(这个诠释正是动态规划最富创造力的精华所在)
从任意节点i到任意节点j的最短路径不外乎2种可能,1是直接从i到j,2是从i经过若干个节点k到j。所以,我们假设Dis(i,j)为节点u到节点v的最短路径的距离,对于每一个节点k,我们检查Dis(i,k) + Dis(k,j) < Dis(i,j)是否成立,如果成立,证明从i到k再到j的路径比i直接到j的路径短,我们便设置Dis(i,j) = Dis(i,k) + Dis(k,j),这样一来,当我们遍历完所有节点k,Dis(i,j)中记录的便是i到j的最短路径的距离。
/* 用邻接矩阵表示的图的Dijkstra算法的源程序*/ #include <iostream>
using namespace std;
#define MAXVEX 100
#define MAX 1e+8
typedef char VexType;
typedef float AdjType; typedef struct
{
int n; //图的顶点个数
// VexType vexs[MAXVEX]; //顶点
AdjType arcs[MAXVEX][MAXVEX]; //边
}GraphMatrix; typedef struct {
// VexType vertex; //顶点信息
AdjType length; // 最短路径长度
int prevex; // 从v0到达vi(i=1,2,…n-1)的最短路径上vi的前驱顶点
}Path;
Path dist[]; // n为图中顶点个数 void dijkstra(GraphMatrix graph, Path dist[])
{
int i,j,minvex;
AdjType min; // 初始化,此时集合U中只有顶点v0
dist[].length = ; dist[].prevex = ;
graph.arcs[][] = ; // 表示顶点v0在集合U中 for(i = ; i < graph.n; i++)
{ // 初始化集合V-U中顶点的距离值
dist[i].length=graph.arcs[][i];
if (dist[i].length != MAX)
dist[i].prevex=;
else dist[i].prevex= -;
}
for(i = ; i < graph.n; i++)
{
min=MAX; minvex=;
for (j = ; j < graph.n; j++) //在V-U中选出距离值最小顶点
if( graph.arcs[j][j] == && dist[j].length < min )
{
min=dist[j].length; minvex=j;
}
if(minvex == ) break; // 从v0没有路径可以通往集合V-U中的顶点
graph.arcs[minvex][minvex] = ; // 集合V-U中路径最小的顶点为minvex
for (j = ; j < graph.n; j++)
{
// 调整集合V-U中的顶点的最短路径
if(graph.arcs[j][j] == ) continue;
if(dist[j].length > dist[minvex].length + graph.arcs[minvex][j]) {
dist[j].length = dist[minvex].length + graph.arcs[minvex][j];
dist[j].prevex = minvex;
}
}
}
} GraphMatrix graph; void initgraph(){
int i,j;
graph.n=;
for (i = ; i < graph.n; i++)
for (j = ; j < graph.n; j++)
graph.arcs[i][j] = (i == j ? : MAX);
graph.arcs[][] = ;
graph.arcs[][] = ;
graph.arcs[][] = ;
graph.arcs[][] = ;
graph.arcs[][] = ;
graph.arcs[][] = ;
graph.arcs[][] = ;
graph.arcs[][] = ;
graph.arcs[][] = ;
graph.arcs[][] = ;
graph.arcs[][] = ;
} int main(){
int i;
initgraph();
dijkstra(graph, dist);
for (i = ; i < graph.n; i++)
printf("(%.0f %d)\t", dist[i].length,dist[i].prevex);
system("pause");
return ;
}
//============================================================================
//Floyed: 往点中间插入其他点,动态:s[i][k] + s[k][j] < s[i][j]
//test case
/
//============================================================================ #include <iostream>
using namespace std;
int main()
{
int n,m,i,j,k,l,r;
cout<<"输入结点数和边数\n";
cin>>n>>m; int**s=new int*[n];//确定的是行数
for(int i=;i<n;i++)
{
s[i]=new int[n];//确定的是列数
}
//初始化,将自己与自己的距离置为0,任意两点距离置为99999
for(i=;i<n;i++){
for(j=;j<n;j++)
{ if(i==j) s[i][j]=;
s[i][j]=;
}
} //Input:
cout<<"输入结点和两个结点的权值\n";
for(k=;k<m;k++)
{
cin>>i>>j;
cin>>s[i][j];
} for (k=; k<n; k++)
for (i=; i<n; i++)
for (j=; j<n; j++)
if (s[i][k] + s[k][j] < s[i][j])
s[i][j] = s[i][k] + s[k][j];
cout<<"输入起始和终止结点"<<endl;
cin>>l>>r;
cout<<s[l][r]<<endl;
system("pause");
return ;
}
* */
最新文章
- Linux From Scratch(从零开始构建Linux系统,简称LFS)- Version 7.7(一)
- C# ListView用法详解
- 四种读写方案IO流 (JAVA)
- Java事务处理全解析(四)—— 成功的案例(自己实现一个线程安全的TransactionManager)
- Linux splint命令
- android 平台搭建
- GitHub问题之恢复本地被删除的文件
- HTML的标签canvas
- 2732: [HNOI2012]射箭( 半平面交 )
- Quartz.NET总结(六)了解Jobs 和 Triggers
- 团队作业4--第一次项目冲刺(Alpha版本)预备工作
- cookie sessionStorage localStorage 之间的关系
- Python项目,VS Code控制台输出乱码问题解决办法
- [hgoi#2019/3/21]NOIP&;NOI赛后总结
- exgcd求解同余方程的最小正整数解 poj1061 poj2115
- Django复习2
- Jni 线程JNIEnv,JavaVM,JNI_OnLoad(GetEnv返回NULL?FindClass返回NULL?)
- 建立SQL链接服务器
- 诡异的 ERROR 1045 (28000): Access denied for user 错误
- 分享一个excel根据文件超链接获取链接文档的最后更新时间