[C++] 多源最短路径(带权有向图):【Floyd算法(动态规划法)】 VS nX Dijkstra算法(贪心算法)

1 Floyd算法

1.1 Code

/**
 * 弗洛伊德(Floyd)算法:
        1 解决问题: 多源最短路径问题
                        求每一对顶点之间的最短路径
                        Background: 带权有向图
        2 算法思想: 动态规划(DP, Dynamic Programming)
        3 时间复杂度: O(n^3)
 */
#include<stdio.h>
#include<iostream>
using namespace std;

// 1 定义图模型(邻接矩阵表示法)的基本存储结构体
# define MaxInt 32767 // 表示极大值 即 ∞ (无穷大)
# define MVNum 100 // 最大顶点数
typedef int VertexType; // 假设顶点的数据类型为整型
typedef int ArcType; // 假设Vi与Vj之边的权值类型为整型
typedef struct {
    VertexType vexs[MVNum]; // 顶点表 (存储顶点信息)
    ArcType arcs[MVNum][MVNum]; // 邻接矩阵
    int vexnum,arcnum; // 图的当前顶点数与边数
}AMGraph; // Adjacent Matrix Graph 邻接矩阵 

// 2 定义Floyd算法的辅助数据结构体
ArcType D[MVNum][MVNum]; // 记录顶点Vi和Vj之间的最短路径长度
int Path[MVNum][MVNum];  // 最短路径上顶点Vj的前一顶点的序号 

/////////////////////// ↓算法区↓ ///////////////////////

void ShortestPath_Floyd(AMGraph G){
    //step1 初始化各对结点的已知路径和距离
    for(int i=0;i<G.vexnum;i++){
        for(int j=0;j<G.vexnum;j++){
            D[i][j] = G.arcs[i][j]; //D[i][j] 初始化
            if(D[i][j]<MaxInt && i!=j){ // 【易漏】 i != j (防止产生自回环)
                Path[i][j] = i; // 若 Vi与Vj之间存在弧(有序顶点对): 将Vj的前驱置为 Vi
            } else {
                Path[i][j] = -1;
            }
        }
    }
    //step2 动态规划(DP)动态更新: <Vi,Vj>更短的最短路径的距离和路径
    for(int k=0;k<G.vexnum;k++){ // 【易错】 中间结点Vk的循环 是在最外层
        for(int i=0;i<G.vexnum;i++){
            for(int j=0;j<G.vexnum;j++){
                if(D[i][k] + D[k][j] < D[i][j]){ // 若从Vi【经Vk】到Vj的一条路径更短
                    D[i][j] = D[i][k] + D[k][j]; // 更新D[i][j]
                    Path[i][j] = Path[k][j]; // 【易错】 更改Vj的前驱为 Vk
                }
            }
        }
    }
} 

// 初始化(邻接矩阵)带权有向图的图模型
void InitAMGraph(AMGraph &G){
    cout<<"Please Input Vertexs Number:";
    cin>>G.vexnum;
    cout<<"\nPlease Directed Edge Number:";
    cin>>G.arcnum;

    for(int i=0;i<MVNum;i++){
        for(int j=0;j<MVNum;j++){
            if(i!=j){ // 【易错】 初始化<Vi, Vj>时: <Vi,Vj> 路径长度无穷大 (i!=j)
                G.arcs[i][j] = MaxInt;
            } else { //  【易错】 初始化<Vi, Vj>时: <Vi,Vi>【自回环】路径长度为0 (i==i)
                G.arcs[i][j] = 0;
            }
        }
    }
    for(int i=0;i<G.vexnum;i++){
        G.vexs[i] = i;
    }
    cout<<"\nPlease Input All Directed Edges and their Weight now.";
    int i,j;
    int weight;
    for(int k=0;k<G.arcnum;k++){
        cout<<"\n("<<(k+1)<<") Directed Edges(i,j,weight): ";
        cin>>i;
        cin>>j;
        cin>>weight;
        G.arcs[i][j] = weight;
    }
    cout<<endl;
}

void OutputD(AMGraph G){
    for(int i=0;i<G.vexnum;i++){
        for(int j=0;j<G.vexnum;j++){
            cout<<"Shortest Distance Weight of the Pair of Directed Vertices ("<<i<<","<<j<<"): "<<D[i][j]<<endl;
        }
    }
}

void OutputPath(AMGraph G){
    for(int i=0;i<G.vexnum;i++){
        for(int j=0;j<G.vexnum;j++){
            cout<<"Path("<<i<<","<<j<<"): "<<Path[i][j]<<endl;
        }
    }
//  int fullPath[G.vexnum]; //逆序记录 <Vi,Vj>的最短路径的序号 ; 最大路径长度不会超过 G.vexnum
//  for(int i=0;i<G.vexnum;i++){
//      for(int j=0;j<G.vexnum;j++){
//          cout<<"Shortest Distance Path of the Pair of Directed Vertices ("<<i<<","<<j<<"): ";
//          for(int p=0;i<G.vexnum;p++){ // 初始化记录最短路径的临时表
//              fullPath[p]= -1; // -1 表示结束符
//          }
//          int m=i,n=j;
//          int cusor=G.vexnum-1;
//          while( (cusor>=0) && (Path[m][n]!=i || Path[m][n]!=MaxInt) ){
//              fullPath[cusor] = Path[m][n]; // Vj的前驱
//              n = fullPath[cusor]; // 【重难点】 源点m不变, 终点n更新为j的前驱
//              cusor--; // 要保证 cusor>=0
//          }
//          //输出全路径
//          cout<<" "<<i<<">";
//          cusor++; // 当前cusor的位置是源点i的前一个空置空间,值为-1
//          while(fullPath[cusor] != -1){
//              cout<<fullPath[cusor]<<">"
//          }
//      }
//  }
}

int main(){
    AMGraph G;
    InitAMGraph(G);//易错处
    ShortestPath_Floyd(G); // 【重/难点】易错处
    OutputD(G);
    OutputPath(G);
    return 0;
}
*/

1.2 Output

Please Input Vertexs Number:4

Please Directed Edge Number:8

Please Input All Directed Edges and their Weight now.
(1) Directed Edges(i,j,weight): 0 1 1

(2) Directed Edges(i,j,weight): 1 3 2

(3) Directed Edges(i,j,weight): 2 0 3

(4) Directed Edges(i,j,weight): 0 3 4

(5) Directed Edges(i,j,weight): 2 1 5

(6) Directed Edges(i,j,weight): 3 2 6

(7) Directed Edges(i,j,weight): 2 3 8

(8) Directed Edges(i,j,weight): 1 2 9

Shortest Distance Weight of the Pair of Directed Vertices (0,0): 0
Shortest Distance Weight of the Pair of Directed Vertices (0,1): 1
Shortest Distance Weight of the Pair of Directed Vertices (0,2): 9
Shortest Distance Weight of the Pair of Directed Vertices (0,3): 3
Shortest Distance Weight of the Pair of Directed Vertices (1,0): 11
Shortest Distance Weight of the Pair of Directed Vertices (1,1): 0
Shortest Distance Weight of the Pair of Directed Vertices (1,2): 8
Shortest Distance Weight of the Pair of Directed Vertices (1,3): 2
Shortest Distance Weight of the Pair of Directed Vertices (2,0): 3
Shortest Distance Weight of the Pair of Directed Vertices (2,1): 4
Shortest Distance Weight of the Pair of Directed Vertices (2,2): 0
Shortest Distance Weight of the Pair of Directed Vertices (2,3): 6
Shortest Distance Weight of the Pair of Directed Vertices (3,0): 9
Shortest Distance Weight of the Pair of Directed Vertices (3,1): 10
Shortest Distance Weight of the Pair of Directed Vertices (3,2): 6
Shortest Distance Weight of the Pair of Directed Vertices (3,3): 0
Path(0,0): -1
Path(0,1): 0
Path(0,2): 3
Path(0,3): 1
Path(1,0): 2
Path(1,1): -1
Path(1,2): 3
Path(1,3): 1
Path(2,0): 2
Path(2,1): 0
Path(2,2): -1
Path(2,3): 1
Path(3,0): 2
Path(3,1): 0
Path(3,2): 3
Path(3,3): -1

2 参考文献

  • 《数据结构(C语言版/ 严蔚敏 李冬梅 吴伟民 编)》

原文地址:https://www.cnblogs.com/johnnyzen/p/11612481.html

时间: 2024-09-30 09:31:26

[C++] 多源最短路径(带权有向图):【Floyd算法(动态规划法)】 VS nX Dijkstra算法(贪心算法)的相关文章

单源最短路径(Dijkstra)——贪心算法

Dijkstra算法是解单源最短路径问题的贪心算法.其基本思想是,设置顶点集合点集合S并不断地做贪心选择来扩充这个集合.一个顶点属于集合S当且仅当从源到该顶点的最短路径长度已知.初始时,S中仅含有源.设u是G的其一顶点.把从源到u且中间只经过S中顶点的路称为从源到u的特殊路径,并用数组Distance记录当前每个顶点所对应的最短特殊路径长度.Dijkstra算法每次从V-S中取出具有最短特殊路长度的顶占,Distance就记录了从源到所有其它顶点之间最短路径长度. 例如下图中的有向图,应用Dij

为什么Prim算法不适用于带权有向图

其实,能不能使用Prim算法计算图的最小生成树,和这个图是有向图还是无向图,这两者之间没有必然的联系. 而是,如果在有向图中出现了以下情况,那么就不能使用Prim算法: 假设一个有向图有3个顶点1->2 8,1->3 8,2->3 4,3->2 3 四条边,由于1->2和1->3是相等的所以prim因为循环顺序的原因最后结果构造出来的树是1->2->3但是答案应该是1->3->2 之所以造成这样的情况,原因只有一个,那就是,在有向图中,有可能存在

有向网络(带权的有向图)的最短路径Dijkstra算法

什么是最短路径? 单源最短路径(所谓单源最短路径就是只指定一个顶点,最短路径是指其他顶点和这个顶点之间的路径的权值的最小值) 什么是最短路径问题? 给定一带权图,图中每条边的权值是非负的,代表着两顶点之间的距离.指定图中的一顶点为源点,找出源点到其它顶点的最短路径和其长度的问题,即是单源最短路径问题. 什么是Dijkstra算法? 求解单源最短路径问题的常用方法是Dijkstra(迪杰斯特拉)算法.该算法使用的是贪心策略:每次都找出剩余顶点中与源点距离最近的一个顶点. 算法思想 带权图G=<V,

带权图的最短路径算法(Dijkstra)实现

一,介绍 本文实现带权图的最短路径算法.给定图中一个顶点,求解该顶点到图中所有其他顶点的最短路径 以及 最短路径的长度.在决定写这篇文章之前,在网上找了很多关于Dijkstra算法实现,但大部分是不带权的.不带权的Dijkstra算法要简单得多(可参考我的另一篇:无向图的最短路径算法JAVA实现):而对于带权的Dijkstra算法,最关键的是如何“更新邻接点的权值”.本文采用最小堆主辅助,以重新构造堆的方式实现更新邻接点权值. 对于图而言,存在有向图和无向图.本算法只需要修改一行代码,即可同时实

Dijkstra算法求单源最短路径

1.最短路径 在一个连通图中,从一个顶点到另一个顶点间可能存在多条路径,而每条路径的边数并不一定相同.如果是一个带权图,那么路径长度为路径上各边的权值的总和.两个顶点间路径长度最短的那条路径称为两个顶点间的最短路径,其路径长度称为最短路径长度. 最短路径在实际中有重要的应用价值.如用顶点表示城市,边表示两城市之间的道路,边上的权值表示两城市之间的距离.那么城市A到城市B连通的情况下,哪条路径距离最短呢,这样的问题可以归结为最短路径问题. 求最短路径常见的算法有Dijkstra算法和Floyd算法

[C++]单源最短路径:迪杰斯特拉(Dijkstra)算法(贪心算法)

1 Dijkstra算法 1.1 算法基本信息 解决问题/提出背景 单源最短路径(在带权有向图中,求从某顶点到其余各顶点的最短路径) 算法思想 贪心算法 按路径长度递增的次序,依次产生最短路径的算法 [适用范围]Dijkstra算法仅适用于[权重为正]的图模型中 时间复杂度 O(n^3) 补充说明 亦可应用于[多源最短路径](推荐:Floyd算法(动态规划,O(n^3))) Dijkstra 时间复杂度:O(n^3) 1.2 算法描述 1.2.1 求解过程(具体思路) 1.2.2 示例 1.2

单源最短路径算法---Dijkstra

Dijkstra算法树解决有向图G=(V,E)上带权的单源最短路径问题,但是要求所有边的权值非负. 解题思路: V表示有向图的所有顶点集合,S表示那么一些顶点结合,从源点s到该集合中的顶点的最终最短路径的权值(程序中用dist[i]表示)已经确定.算法反复选择具有最短路径估计的顶点u 属于 V-S(即未确定最短路径的点,程序中finish[i]=false的点),并将u加入到S中(用finish[i]=true表示),最后对u的所有输出边进行松弛. 程序实现:      输入数据: 5 7 0

Til the Cows Come Home(poj 2387 Dijkstra算法(单源最短路径))

Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 32824   Accepted: 11098 Description Bessie is out in the field and wants to get back to the barn to get as much sleep as possible before Farmer John wakes her for the morning milking. Bessi

Bellman-Ford 单源最短路径算法

Bellman-Ford 算法是一种用于计算带权有向图中单源最短路径(SSSP:Single-Source Shortest Path)的算法.该算法由 Richard Bellman 和 Lester Ford 分别发表于 1958 年和 1956 年,而实际上 Edward F. Moore 也在 1957 年发布了相同的算法,因此,此算法也常被称为 Bellman-Ford-Moore 算法. Bellman-Ford 算法和 Dijkstra 算法同为解决单源最短路径的算法.对于带权有向