floyd(多源最短路)

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

Floyd算法是一个经典的动态规划算法。用通俗的语言来描述的话,首先我们的目标是寻找从点i到点j的最短路径。从动态规划的角度看问题,我们需要为这个目标重新做一个诠释(这个诠释正是动态规划最富创造力的精华所在)

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

关于这个floyd 更详细的解释 在一个大神的博客中 DP 解释 ,大家可以自己看看。

floyd 的应用

1.找出负环

就像贝尔曼福特一样,我们在不断的松弛(只要还有边可以松弛),只要存在负环,他就可以一直松弛,对于一个正常的图,floyd使用了n^3的复杂度,对于每一个中间点,我们都进行一个二重循环,尽量将所有的边和点都照顾到,如果没有负环,到最后肯定是任意两点之间都是最短路。出现负环,这个环内,每一个边都是负的,我们在这里判断一下就可以了,出现了负的边,我们就及时的退出,避免TLE,毕竟n^3 的复杂度。(跑数据可以借鉴bell_man ford 里面那个测试代码)。

2.到不了的点。

如果有到不了的节点的话,maap[maxn][maxn]就是inf ,因为可能存在负的环,如果我们到不了这个点的时候,这个点本应该就是inf 的,但是 你可能有负环,他可能就不是inf 了,所以我们在敲代码的时候,我们就应该避免这个事情,就是一个点到不了一个中间点的时候,我们就不用再去找那个中点了(起始都到不了那个中间点,就不用再去看中间点到中间点了,避免inf 因为负环而改变)。同样,如果一个中间点到不了一个终点,我们也要及时continue,避免出错,如果有一条路的话,比较直接到达短还是间接到达短,取那个最小值。

floyd 模板 :
 

#include
const int maxn=115;
typedef long long ll;
const ll inf =0x3f3f3f3f3f3f3f3f;
using namespace std;
ll maap[maxn][maxn];

int n,m;

void init()
{
	for(int i=0;imaap[i][k]+maap[k][j])
					maap[i][j]=maap[i][k]+maap[k][j];
			}
			if(maap[i][i]<0)
				return true;
		}
	return false;
}

int main()
{
	cin>>n>>m;
	init();
	int u,v,val;
	for(int i=0;i>u>>v>>val;
		if(maap[u][v]>val)
		{
			maap[u][v]=val;
		}
	}
	if(floyd())
		cout<<"NEGATIVE CYCLE"<

就是上面这个模板,主要还是应用到了那个DP的思想。

你可能感兴趣的:(图论)