zoukankan      html  css  js  c++  java
  • 【学习笔记】Floyd的妙用

    【学习笔记】Floyd的妙用

    前言

    (floyd)是一个广为人知的多源最短路算法,时间复杂度(O(N^3))。事实上,(floyd)有一些其他的用法。本文旨在介绍这些用法,欢迎补充

    1.最短路计数

    单纯的最短路计数,事实上也能通过(SPFA)实现。而求两点之间经过某个点的最短路路径数,实现可以用两次(SPFA)。假若时间复杂度允许,亦可用下面介绍的方法,代码较为简单。

    P2047 [NOI2007]社交网络

    这道题是多源最短路,所以用(floyd)实现求最短路。

    (f[i][j])(i)(j)最短路长度,(s[i][j])为最短路径数。对于一点(k),如果(f[i][k]+f[k][j]=f[i][j]),则经过该点的最短路径条数为(s[i][k] imes s[k][j])

    2.经过(k)条边

    对于诸如求两点之间经过(k)条边的最短路长度/路径数的问题,用(dij/SPFA)较难实现,这时候可以尝试使用(floyd)。下面通过例题介绍。

    P2886 [USACO07NOV]牛继电器Cow Relays

    在本题中,用(SPFA)直接求空间会爆,只能考虑使用(floyd)求经过(1le Kle k)条路径的最短路。(k)如此大以至于会(TLE)。于是我们可以通过倍增解决。

    题解

    BTW,本题也可以通过矩阵快速幂解决,详情请见info___tion的blog

    3.最小环

    度度熊保护村庄

    (floyd)可以求无向图和有向图的最小环。

    对于在有向图中,求经过第(i)个点的最小环,我们可以把(f[i][i]= infin),跑一遍(floyd),则最小环为(f[i][i])

    而在无向图中,方法有些不同。因为不能重复经过某一条边,上述方法为错解。

    依照(floyd)的实现方式,在第 (k) 轮循环中,(f_{i,j})记录的是在只经过前 (k) 点的情况下从 (i)(j) 的最短路

    类似的,在第 (k) 轮循环中,用(f_{k,k})记录的是在只经过前 (k) 点的情况下从 (k)(k) 的最短路,即以 (k) 为编号最大的点的最小环的长度

    该环由三部分组成:从 (k)(i) 的一条边,(i)(j) 的多条边, (j)(k) 的一条边。

    那么用第 (k-1) 轮循环得出的 (f),更新(f_{k,k})即可

    代码如下

    	for (int k=1;k<=n;k++)
    	{
    		for (int i=1;i<=n;i++)
    		{
    			for (int j=1;j<=n;j++)
    			{	  
    			  if (i!=j&&i<=k&&j<=k) f[k][k]=min(f[k][k],e[i][k]+e[k][j]+f[i][j]);
    			}
    		}
    		for (int i=1;i<=n;i++)
    		{
    			for (int j=1;j<=n;j++)
    			{	  
    			  if (i!=j) f[i][j]=min(f[i][j],f[i][k]+f[k][j]); 
    			}
    		}
    	}
    

    而对于上面的例题,我们还需要用叉积判断是否所有点都在边的同一边,再根据实际情况建单向边,详情看大佬题解

    4.图的传递闭包

    这东西(OI)好像不常考?

    那么就咕掉吧。

    丢链接

    总结

    (floyd)不仅可以求多源最短路,也可以求一些base on最短路的问题。不过由于其时间复杂度较大,需要谨慎使用

  • 相关阅读:
    python爬虫之urllib
    python 数据库操作类
    Vue学习之路第十篇:简单计算器的实现
    Vue学习之路第九篇:双向数据绑定 v-model指令
    Vue学习之路第八篇:事件修饰符
    Vue学习之路第七篇:跑马灯项目实现
    Vue学习之路第六篇:v-on
    Vue学习之路第五篇:v-bind
    Vue学习之路第四篇:v-html指令
    Vue学习之路第三篇:插值表达式和v-text的区别
  • 原文地址:https://www.cnblogs.com/fmj123/p/11288430.html
Copyright © 2011-2022 走看看