图的最短路径:Floyd、DisjKstra、SPFA算法

版权声明:本文为博主原创文章,博客地址:https://blog.csdn.net/qq_41855420,未经博主允许不得转载。 https://blog.csdn.net/qq_41855420/article/details/89785974

问题描述:

给定一个有向图的邻接矩阵graph,graph[i][j]表示点i到点j的路径长,我们需要对图进行稀疏,将graph[i][j]转换为点i到点j的最短路径长。
图的稀疏是图中比较经典的问题,常见的算法有Floyd、DisjKstra、SPFA算法,下面将进行详述。

一、 F l o y d \color{blue}{Floyd算法}

Floyd-Warshall算法(Floyd-Warshall algorithm)是解决任意两点间的最短路径的一种算法,可以正确处理有向图或负权的最短路径问题,同时也被用于计算有向图的传递闭包。Floyd-Warshall算法的时间复杂度为O(N3),空间复杂度为O(N2)。

从任意节点i到任意节点j的最短路径有两种情况,1是直接从i到j,2是从i经过若干个节点k到j。所以,我们假设Dis(i,j)为节点i到节点j的最短路径的距离,对于每一个节点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的最短路径的距离。

算法实现:
void floyd(vector<vector<int>> &graph, int N){
    for (int i = 1; i <= N; ++i){
        for (int j = 1; j <= N; ++j){
            //前两层for循环用于穷举graph[i][j],任意两点i、j之间的距离
            for (int k = 1; k <= N; ++k){
                //第三层for循环用于穷举中间稀疏节点
                graph[i][j] = min(graph[i][j], graph[i][k] + graph[k][j]);
            }
        }
    }
}

二、 D i s j K s t r a \color{blue}{DisjKstra算法}

Dijkstra(迪杰斯特拉)算法是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法。是从一个顶点到其余各顶点的最短路径算法,解决的是有权图中最短路径问题。迪杰斯特拉算法主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。Dijkstra算法是很有代表性的最短路径算法,在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹学等等。 \color{red}{注意该算法要求图中不存在负权边}

算法描述:

比如我们现在需要求点K到各个点的最短距离,我们先定义一个数组distToK[N]表示点K到各个点的最短距离。并且使用一个队列放入需要搜索的点,把点A放入队列。已知输入为vector<vector<int>> &graph, int N, int K

while 队列不为空:
	获取当前队头front,并且出队
	for (int i = 1; i <= N; ++i){
		if distToK[front](点A到点front的距离) + graph[front][i](点front到点i的距离) < distToK[i](点A到点i的距离)	{
			distToK[i] = distToK[front] + graph[front][i]
			并且将点i放入到队列的尾部
		}
	}
算法示意图:

在这里插入图片描述

算法实现:
//vector<vector<int>> &graph输入的图的邻接矩阵,graph[i][j]表示i到j的距离,N表示图中节点的个数
vector<int> networkDelayTime(vector<vector<int>> &graph, int N, int K) {
    queue<int> myQue;//结点队列
    myQue.push(K);
    vector<int> distToK(N + 1, INT_MAX);//distToK[index]表示点K到点index的最短距离,初始化为无穷大
    distToK[K] = 0;//K到自己的最短距离为0
    //开始搜索各个点到k的最短距离
    while(!myQue.empty()){
        int front = myQue.front();//获取当前队头
        myQue.pop();
        //利用当前front节点,尝试稀疏点k到所有节点的最短距离
        for(int target = 1; target <= N; ++target){
            if(graph[front][target] != -1 && distToK[front] + graph[front][target] < distToK[target]){
                //如果front到target有边,并且点k到front的距离distToK[front] + 点front到target距离graph[front][target]小于点k到target的距离distToK[target]
                distToK[target] = distToK[front] + graph[front][target];//则进行稀疏
                myQue.push(target);//放入队列
            }
        }
    }
    return distToK;
}

三、 S P F A \color{blue}{SPFA算法}

未完待续。

猜你喜欢

转载自blog.csdn.net/qq_41855420/article/details/89785974
今日推荐