最短路径---Floyd-Warshall

简单介绍

  • 这个算法可以用来求一个图中任意两个点的最短路径,也被称为 “多源最短路径” 问题

讲解

  • 我们可以用二维数组来存储各点间的距离信息,将没有办法直接到达的用无穷大来表示,自己到自己用0来表示,这样我们就得到了图的信息
  • 但如何求两点间的最短路径?
  1. 如图,是储存好的一张图(图有四个点,八条边)
    在这里插入图片描述
  2. 从图可以知道,我们并不能从2点直接到1点,但我们可以借助一个中转站,如我们可以先从2点到3点,距离为3,然后从3点到1点,距离为7,这样我们便有知道了2点可以通过9的距离到达1点
  3. 从图还可以得到,1点直接到3点的距离为6,但我们通过2这个中转点,便能将距离缩短为5
  4. 通过上面这例子,我们便知道了每个顶点都有可能使另外两个顶点的路程变短,但我们不能毫无目的的寻找
  5. 假如现在只允许经过一号顶点,求任意两点间的最短路程只需判断e[i][1]+e[1][j]是否比e[i][j]小
    代码实现
for(i=1;i<=n;i++){
	for(j=1;j<=n;j++){
		if(e[i][1]+e[1][j]<e[i][j])
			e[i][j]=e[i][1]+e[1][j];
	}
}

最短路程更新如下:
在这里插入图片描述

  1. 然后2号顶点加进来,看只允许1,2号点做中转点的情况能使那些距离改变,再依次增加,看1,2,3点做中转点,1,2,3,4做中转点可以改变的距离
  2. 下面是整个算法的核心代码(只有5行)
for(k=1;k<=n;k++){
	for(i=1;i<=n;i++){
		for(j=1;j<=n;j++){
			if(e[i][k]+e[k][j]<e[i][j])
				e[i][j]=e[i][k]+e[k][j];
		}
	}
}

完整代码

#include<stdio.h>
#define MAX 999999
int main(){
	int e[10][10],i,j,k,n,m,t1,t2,t3;
	scanf("%d %d",&n,&m);//输入点的个数和边的条数 
	//初始化数组 
	for(i=1;i<=n;i++){
		for(j=1;j<=n;j++){
			if(i==j)
				e[i][j]=0;
			else
				e[i][j]=MAX;
		}
	}
	//读入各边的距离 
	for(i=1;i<=m;i++){
		scanf("%d %d %d",&t1,&t2,&t3);
		e[t1][t2]=t3;
	}
	//核心算法 
	for(k=1;k<=n;k++){
		for(i=1;i<=n;i++){
			for(j=1;j<=n;j++){
				if(e[i][k]+e[k][j]<e[i][j])
					e[i][j]=e[i][k]+e[k][j];
			}
		}
	}
	//输出图 
	/*for(i=1;i<=n;i++){
		for(j=1;j<=n;j++){
			printf("%d ",e[i][j]);
		}
		printf("\n");
	}*/ 
	
	//输入想知道最短距离的两个点
	scanf("%d %d",&i,&j);
	printf("点%d和点%d的最短距离是:%d",i,j,e[i][j]); 
	
	return 0;
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值