时间复杂度
O(n3),n是端点数。
核心代码
template
class CNeiBoMat
{
public:
CNeiBoMat(int n, const vector
{
m_vMat.assign(n, vector
for (int i = 0; i < n; i++)
{
m_vMat[i][i] = 0;
}
for (const auto& v : edges)
{
m_vMat[v[0]- b1Base][v[1]- b1Base] = v[2];
if (!bDirect)
{
m_vMat[v[1]- b1Base][v[0]- b1Base] = v[2];
}
}
}
vector
};
- //多源码路径
- template<class T, T INF = 1000 * 1000 * 1000>
- class CFloyd
- {
- public:
- CFloyd(const vector
>& mat) - {
- m_vMat = mat;
- const int n = mat.size();
- for (int i = 0; i < n; i++)
- {//通过i中转
- for (int i1 = 0; i1 < n; i1++)
- {
- if (INF == m_vMat[i1][i])
- {
- continue;
- }
- for (int i2 = 0; i2 < n; i2++)
- {
- //此时:m_vMat[i1][i2] 表示通过[0,i)中转的最短距离
- m_vMat[i1][i2] = min(m_vMat[i1][i2], m_vMat[i1][i] + m_vMat[i][i2]);
- //m_vMat[i1][i2] 表示通过[0,i]中转的最短距离
- }
- }
- }
- };
- vector
> m_vMat; - };
原理
当一层循环执行完后,m_vMat[i1][i2]表示经过[0,i)中的任意个点的最短距离。
初始状态下, m_vMat[i1][i2]表示直达的最小距离,也就是经过0个点。
通过[0,i)中任意个点,i1到i2的最短路径记为PrePathi1i2,通过[0,i+1)中任意个点,i1到i2的距离的路径为Pathi1i2,如果Path不经过Pathi1i2,则和PrePathi1i2相同。如果经过则可以拆分成{i1…i}+{i…i2},显然{i1…i}是PrePathi1i,{i…i2}是PrePathii2,否则替换成PrePathi1i和PrePathii2。
m_vMat同时表示PreMath和Math,如果m_vMat[i1][i]或m_vMat[i][i2]已经更新,会带来错误的结果么?结果是不会,会更新但值不变。
当i1等于i时:
m_vMat[i][i2] = min(…, m_vMat[i][i] + m_vMat[i][i2]);
由于m_vMat[i][i]为0,所以右式就是左式。
当i2等于i时,类似。
样例
假定有5个点,前4个点连通。整个处理流程如下:
初始状态 | 处理完i等于0(不变) | |||||||||
0 | 1 | 4 | INF | INF | ||||||
1 | 0 | 2 | 4 | INF | ||||||
4 | 2 | 0 | 3 | INF | ||||||
INF | 4 | 3 | 0 | INF | ||||||
INF | INF | INF | INF | 0 | ||||||
处理完i等于1 | 处理完i等于2(不变) | |||||||||
3 | 5 | |||||||||
3 | ||||||||||
5 | ||||||||||
处理完i等于3,结果不变 | 最终结果 | |||||||||
0 | 1 | 3 | 5 | INF | ||||||
1 | 0 | 2 | 4 | INF | ||||||
3 | 2 | 0 | 3 | INF | ||||||
5 | 4 | 3 | 0 | INF | ||||||
INF | INF | INF | INF | 0 |
测试样例
#include
#include
using namespace std;
struct CDebugParam
{
int n;
vector
vector
};
int main()
{
const int INF = 1000 * 1000 * 1000;
vector
{
{0,1,3,5,INF},
{1,0,2,4,INF},
{3,2,0,3,INF},
{5,4,3,0,INF},
{INF,INF,INF,INF,0}
}
} };
for (const auto& param : params)
{
CNeiBoMat
CFloyd
for (int r = 0; r < param.n; r++)
{
for (int c = 0; c < param.n; c++)
{
assert(param.result[r][c] == floyd.m_vMat[r][c]);
}
}
}
}
其它
源码及测试样例下载
https://download.csdn.net/download/he_zhidan/88393631
其它
视频课程
基础算法的C++实现课程,请点击下面的CSDN学院的链接。
https://edu.csdn.net/course/detail/38771
我还做了其它课程,比如:C++入职培训,C#入职培训。
https://edu.csdn.net/lecturer/6176
运行验证环境
Win10 VS2022 Ck++17 或win7 VS2019 C++17
相关下载
如果你时间宝贵,只想看精华,请到CSDN下载频道下载《闻缺陷则喜算法册》doc版
https://download.csdn.net/download/he_zhidan/88348653
博主有几句话想对大家说 |
算法是程序的灵魂,没有好的算法,程序就死气沉沉。 |
问题发现得越早,越给老板省钱。我简称为:闻缺陷则喜。 |
有所得,以墨记之,故曰墨家 |



评论记录:
回复评论: