最短路最小生成树的系统总结(更新中)

本文系统总结了最短路算法Floyd和Dijkstra,以及它们的应用和扩展问题,包括最小环的求解、多关键字极短路、K短路等。同时探讨了Dijkstra与Prim算法的相似性,并分析了Kruskal算法在求解最小生成树中的核心思想,即删除环中的最大边。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我这两天好像和这些基础算法干上了。。

不过最短路算法的确还是有非常多非常巧妙的应用让我不得不总结的!  知其然不知其所以然真的是一件很容易触发伤痛的事情啊!

而且其实NOIP的题中本来就不怎么出图论, 出了图论也就是最短路, 并查集, 树上倍增这几种了吧(还有拓扑), 最多是加一些乱七八糟的东西来扰人耳目。

而不被干扰的唯一方法就是认清事物的本质, 认清本质需要在更高的一个层面上进行总结, 这也是我日后学习任何算法是应该做的

一, Floyd

暴力而优美的算法,最经典的三个for!

Floyd算法的基本思想如下:从任意节点A到任意节点B的最短路径不外乎2种可能,1是直接从A到B,2是从A经过若干个节点X到B。所以,我们假设Dis(AB)为节点A到节点B的最短路径的距离,对于每一个节点X,我们检查Dis(AX) + Dis(XB) < Dis(AB)是否成立,如果成立,证明从A到X再到B的路径比A直接到B的路径短,我们便设置Dis(AB) = Dis(AX) + Dis(XB),这样一来,当我们遍历完所有节点X,Dis(AB)中记录的便是A到B的最短路径的距离。

for(int k = 1; k <= n; k ++)
     for(int i = 1; i <= n; i ++)
          for(int j = 1; j <= n; j ++)
               if(dis[i][j] > dis[i][k] + dis[k][j])
                    dis[i][j] = dis[i][k] + dis[k][j];

值得注意的一点事k 的循环是要放在最外层的。

否则如下图A到B是找不到比9更短的路径的, 但事实上它是存在的。

Floyd找到A到B的最短路时, 需要在这之前找到A到C的最短路和B到C的最短路, 所以只按照i 到 j 的点的顺序循环是不可以的。

依次扫描每一点(k),并以该点作为中介点,计算出通过k点的其他任意两点(i,j)的最短距离,这就是floyd算法的精髓!同时也解释了为什么k点这个中介点要放在最外层循环的原因.

上面一行是我看到一个人的解释, 但感觉还是在用结论证明结论啊。。

我个人的理解是感觉外层的循环像是在求一个连通块, 每访问到一个点K就把所有和K有关的点并起来, 显然在一个连通块中所有度大于1的节点都被当成K访问过, 所以任意两点仅通过集合中节点的最短路是已知的。 那么如果图是连通的, 外层循环访问完所有点后, 原图中任意两点间的最短路就是已知的了!

不知道我这么说是否清楚。。

不过深入地思考下去实在是会觉得Floyd是简约而不简单的。

应用

Floyd最经典的应用就是求最小环了吧

    for(int k = 1; k <= n; k ++){
        for(int i = 1; i <= k; i ++)
            for(int j = 1; j <= k; j ++)
                mincircle = min(mincircle, dis[i][k] + dis[k][j] + lu[i][j]);
        for(int i = 1; i <= n; i ++)
            for(int j = 1; j <= n; j ++)
                if(dis[i][k] + dis[k][j] < dis[i][j])
                    dis[i][j] = dis[i][k] + dis[k][j];    
    }


在第K层外循环中,

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值