floyd

本文详细介绍了Floyd-Warshall算法用于解决图中两点间最短路径的问题,强调了其在处理负权重时的限制。通过实例解析了如何利用Floyd算法寻找无向图中至少含三个点的最小环,并提供了相应的C++代码实现。同时,文章还探讨了Floyd算法的拓展应用,包括倍增Floyd和传递闭包的概念,并以P1613跑路问题为例展示了倍增Floyd在有向图问题中的应用。

【算法介绍】

Floyd 用于求每对点之间的距离,可以单向可以双向,可以正权可以负权,但不能有负环

时间复杂度O(N^3) 本质上可以理解成为一种动态规划算法

 

【模板】

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

 

【题型】

1.floyd 求解最小环

[例题1] Sightseeing Trip poj1734

 

[题意] 无向图求至少含三个点的最小环

[分析] 利用floyd的性质,当外层k循环刚开始的时候,保存着不超过k-1的i到j的最短路,然后我们就可以利用dis[i][j]+e[j][k]+e[k][i]来表示一个环,且这个环经过k,由不超过k的节点组成,这样处理即可,最后加上路径处理

[代码]

#include<bits/stdc++.h>
using namespace std;
int n,m;
const int maxn=105;
int e[maxn][maxn],dis[maxn][maxn],pos[maxn][maxn];
vector <int> path;
#define pb push_back
void write(int x,int y)
{
	if(!pos[x][y]) return;
	write(x,pos[x][y]);
	path.pb(pos[x][y]);
	write(pos[x][y],y);
}
int main()
{
	freopen("a.in","r",stdin);
	freopen("a.out","w",stdout);
	scanf("%d%d",&n,&m);
	memset(e,0x3f,sizeof(e));
	for(int i=1;i<=m;i++)
	{
		int x,y,z;
		scanf("%d%d%d",&x,&y,&z);
		e[x][y]=e[y][x]=min(z,e[x][y]); //这种写法处理重边!! 
	}
	memcpy(dis,e,sizeof(e));
	int ans=0x3f3f3f3f;
	for(int k=1;k<=n;k++)
	{
		for(int i=1;i<k;i++)
			for(int j=i+1;j<k;j++)
			{
				if((long long)dis[i][j]+e[j][k]+e[i][k]<ans) //这个左侧的long long不开会WA两个点 
				{
					ans=dis[i][j]+e[j][k]+e[i][k];
					path.clear(); path.pb(i);
					write(i,j);
					path.pb(j); path.pb(k);
				}
			}
		//正常的floyd 记录一下转移点 
		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];
					pos[i][j]=k;
				}
	}
	if(ans==0x3f3f3f3f)
		printf("No solution.");
	else
	{
		for(int i=0;i<path.size();i++)
			printf("%d ",path[i]);
	}
	return 0;
}

【拓展】有向图的最小环,可以从1-n做n次dijkstra,然后每次枚举完u的出边,把dis[u]->inf,然后继续处理后面的部分,当第二次更新到dis[u]时出现环,dis[u]就是环

的长度,目前还未找到合适的例题,待补

 

2.倍增floyd

利用矩阵乘法的思想,a[i][j]记录i到j经过若干条边的最短路,然后就是Floyd的思想,再加上快速幂即可

[补1] P1613 跑路

[题意] 有向图,1s可以走正好2^k条边(利用跑路器),或者1s正常走一条边,问1-n 的最短时间

[分析] 这道题很明显在暗示我们考虑倍增了,我们先处理出i->j是否存在正好2^k条边的道路,然后利用floyd即可

 

[代码]

 

传递闭包  利用0/1记录两者的关系,用floyd传递信息

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值