最短路径(弗洛伊德算法 迪杰斯特拉算法 贝尔曼-福特算法)

弗洛伊德算法:

弗洛伊德算法核心代码:

for(int k=0;k<n;k++)
{
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<n;j++)
		{
			dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
		}
	}
}	

上述代码只有五行,时间复杂度是N的三次方。本算法最大的优点就是代码简洁。在对时间复杂度要求不高的情况下,可以通过此算法找到任意两点间或者指定一点到另一点的最小距离。
思路:
寻找两点间的最小距离,我们可以通过引入中间点来寻找最短距离。例如:我们需要寻找i和j两点间的最小距离,那么我们可以引入中间点k,通过判断i到k再到j的距离是否小于此时i到j的距离,如果是,则更新i到j点的距离。此算法运用了动态规划的思想。
具体代码如下:

#include <stdio.h>
int dis[105][105],n,q,a,b,c,Inf=1e9;
int min(int x,int y)
{
	return x<y?x:y;
}
int main()
{
	scanf("%d%d",&n,&q);
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(i!=j)
				dis[i][j]=Inf;
		}
	}
	for(int i=0;i<q;i++)
	{
		scanf("%d%d%d",&a,&b,&c);
		dis[a][b]=min(dis[a][b],c);
	}
	for(int k=1;k<=n;k++)
	{
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=n;j++)
			{
				dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);//防止重边
			}
		}
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
				printf("%d ",dis[i][j]);
		}
		printf("\n");
	}
	return 0;
}

贝尔曼-福特算法

核心代码:

for(int i=0;i<n-1;i++)
{
	for(int j=0;j<m;j++)
	{
		dis[v[j]]=min(dis[v[j]],dis[u[j]]+w[j]);
	}
}

贝尔曼-福特算法用来寻找指定点到其他点的最短距离,并且可以解决迪杰斯特拉算法不能解决的负权值问题。缺点是时间复杂度较高。
上述代码表明,我们有m条边。而我们的目的就是通过选择不同的边来寻找两点间的最短距离。外循环一共循环了n-1次,表示两点间最多有n-1条边。内循环枚举每一条边,通过比较来寻找最多通过i+1条边时,两点间的最短距离。而我们发现,很多情况下,不必循环n-1次,某些点便已经找到了最短距离,此后用这些点去更新所连接的点,不会产生任何影响。这就启发我们,**每次只处理最短路数值发生变化的点,因为只有发生变化的点,与其有临边的点的最短路才有可能变化。**所以我们采用队列优化的方式,来实现贝尔曼-福特算法。
代码如下:

#include <stdio.h>
int n,m,dis[1005],u[1005],w[1005],v[1005],first[1005],next[1005],head,tail,que[10000],temp,b[1005]; //为了减少复杂度,我们采用邻接表储存图
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	{
		next[i]=-1;
		first[i]=-1;
		dis[i]=1e9;
	}
	dis[1]=0;
	for(int i=0;i<n;i++)
	{
		scanf("%d%d%d",&u[i],&v[i],&w[i]);
		next[i]=first[u[i]];      //next[i]储存的是以i号路的上一条路的编号 
		first[u[i]]=i;           //first[u[i]]储存的是以u[i]为顶点的第一条路的编号 
	}
	head=0;
	tail=1;
	que[head]=1;
	temp=first[que[head]];
	while(tail>head)
	{
		while(temp!=-1)
		{
			if(dis[v[temp]]>dis[u[temp]]+w[temp])
			{
				if(!b[v[temp]])
				{
					b[v[temp]]=1;
					que[tail++]=v[temp];
				}
				dis[v[temp]]=dis[u[temp]]+w[temp];
			}
			temp=next[temp];
		 } 
		 book[que[head]]=0;
		 head++;
	}
	for(int i=1;i<=n;i++)
	{
		printf("%d ",dis[i]);
	}
	return 0;
}
发布了31 篇原创文章 · 获赞 11 · 访问量 2573

猜你喜欢

转载自blog.csdn.net/guyjy/article/details/105008971