.弗洛伊德算法求最短路径

  1. 5. 弗洛伊德算法求最短路径

【问题描述】

对于下面一张若干个城市,以及城市之间距离的地图,请采用弗洛伊德算法求出所有城市之间的最短路径。

【输入形式】

顶点个数n,以及n*n的邻接矩阵,其中不可达使用9999表示。

【输出形式】

每两个顶点之间的最短路径和经过的顶点

注意:规定顶点自身到自身的dist值为0,此时path为该顶点编号。

【样例输入】

4

9999 4 11 9999

6 9999 2 9999

1 9999 9999 1

9999 3 9999 9999

【样例输出】

from(空格)0(空格)to(空格)0:(空格)dist(空格)=(空格)0(空格)path:0(换行)

from 0 to 1: dist = 4 path:0 1
from 0 to 2: dist = 6 path:0 1 2
from 0 to 3: dist = 7 path:0 1 2 3
from 1 to 0: dist = 3 path:1 2 0
from 1 to 1: dist = 0 path:1
from 1 to 2: dist = 2 path:1 2
from 1 to 3: dist = 3 path:1 2 3
from 2 to 0: dist = 1 path:2 0
from 2 to 1: dist = 4 path:2 3 1
from 2 to 2: dist = 0 path:2
from 2 to 3: dist = 1 path:2 3
from 3 to 0: dist = 6 path:3 1 2 0
from 3 to 1: dist = 3 path:3 1
from 3 to 2: dist = 5 path:3 1 2
from 3 to 3: dist = 0 path:3

#include <bits/stdc++.h>
using namespace std;
const int inf = 9999;
int arc[55][55];
int n;
int dist[55][55];
vector<int> path[55][55];
void creat()
{
    cin >> n;
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
        {
            cin >> arc[i][j];
            if (i == j)
                arc[i][j] = 0;
        }
}
void floyed()
{
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
        {
            dist[i][j] = arc[i][j];
            if (dist[i][j] != inf && i != j)
            {
                path[i][j].push_back(i);
                path[i][j].push_back(j);
            }
            else if (i == j)
                path[i][j].push_back(i);
            else
                path[i][j].push_back(9999);
        }
    for (int k = 0; k < n; k++)
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n; j++)
                if (dist[i][j] > dist[i][k] + dist[k][j])
                {
                    dist[i][j] = dist[i][k] + dist[k][j];
                    path[i][j].clear();
                    for (int q = 0; q < path[i][k].size() - 1; q++)
                    {
                        path[i][j].push_back(path[i][k][q]);
                    }
                    for (int q = 0; q < path[k][j].size(); q++)
                    {
                        path[i][j].push_back(path[k][j][q]);
                    }
                }
}
void show()
{
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
        {
            if (i == j)
            {
                dist[i][j] = 0;
                path[i][j].clear();
                path[i][j].push_back(i);
            }
            cout << "from " << i << " to " << j << ": "
                 << "dist = " << dist[i][j] << " path:";
            for (int k = 0; k < path[i][j].size(); k++)
            {
                cout << path[i][j][k] << " ";
            }
            cout << endl;
        }
}
int main()
{
    creat();
    floyed();
    show();
}

 

### 关于弗洛伊德算法最短路径的示例题目 #### 示例题目解释 在一个带权有向图 \( G \) 中,给定该图的带权邻接矩阵表示法。目标是计算出此图中任意两个节点之间的最短路径长度。 对于此类问题,可以通过应用弗洛伊德算法来解决。该算法利用了一个三维迭代过程,在每次迭代过程中考虑一个新的中间节点作为潜在的更优路径的一部分[^1]。具体而言: - 初始化阶段设置各点到自身的距离为0,如果两点间存在直接边则设其权重值;否则设定无穷大。 - 接下来遍历每一个可能充当中介角色的顶点k,并更新其他所有成对顶点i,j之间已知的佳路径记录——只要经由当前考察的中介点能使原路径变得更就采纳新方案[^3]。 终得到的结果是一个新的二维数组D,其中\( D[i][j] \)代表从第 i 个结点出发到达 j 结点所经过路程小总。 #### Python 实现代码如下所示: ```python def floyd_warshall(graph): V = len(graph) dist = list(map(lambda i : map(lambda j : j , i) , graph)) for k in range(V): for i in range(V): for j in range(V): dist[i][j] = min(dist[i][j],dist[i][k]+dist[k][j]) return dist if __name__ == "__main__": INF = float('inf') graph = [ [0, 5, INF, 10], [INF, 0, 3, INF], [INF, INF, 0, 1], [INF, INF, INF, 0] ] result = floyd_warshall(graph) print("The shortest path matrix is:") for row in result: formatted_row = ["{:<8}".format(str(x)) if x != INF else "INF".ljust(8) for x in row] print("[{}]".format(", ".join(formatted_row))) ``` 上述程序定义了`floyd_warshall()`函数用于实现弗洛伊德算法逻辑处理部分,以及一个测试用例展示如何调用这个函数并打印输出结果。这里采用的是一个简单的四阶方阵形式输入样例来进行说明[^4]。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wrong Ansewer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值