【弗洛伊德算法】

弗洛伊德算法(Floyd),又称为是插点法。目的是求加权图中顶点中最短路径的方法。本文通过举例子的方法想你具体解释何为弗洛伊德算法。

有一个送礼物的问题,是CSDN上的一个题目,题目的详情是这样的。

题目详情:

HeHe和XiXi在一个地方玩游戏,XiXi把N-1件礼物(HeHe以前送给XiXi的)分别藏在了另外N-1个地方,这些地方都能互相到达,且所有的边都是有方向的。

现在HeHe要做的事就是去那些地方找回那N-1件礼物给XiXi;

由于每一件礼物都有特殊的意义,所以XiXi要求HeHe每找到一件礼物,就必须马上返回XiXi所在的位置,对她说一句当年送她这件礼物的时候所说的话。

由于每走一个单位长度HeHe需要花费1分钟,XiXi还要求HeHe在最快的时间内把这些礼物带回来交给她,你能帮助HeHe么?


输入

测试数据有T组,每组测试数据开始为两个整数N和M,1 <= N,M <= 100000。

N代表所有的位置,M代表这些位置之间的长度

然后是M行,每行有三个数,u,v,w,即位置u和位置v之间有一条单向的边,距离为w;

你可以假设位置的编号是从1到N,XiXi的位置始终都在1;

输出

对于每组测试数据, 用一行输出HeHe所花费的最短时间。


答题说明:

输入样例

1

3 3

1 2 4

2 3 5

3 1 6

输出样例

30

  由这道题目我们可以划出图形:


                                      

可知道,题目需要求得的是:D[1→2]+D[2→1]+D[1→3]+D[3→1]的大小(D[i→j]表示结点i到j的最短距离):4+(5+6)+(4+5)+6=30


最后根据弗洛伊德算法思想写出来代码了,但是在CSDN运行时会出错。不过思想是没错的,大家可以根据代码理解下弗洛伊德

#include <stdio.h>
#include <string.h>

#define MAX 10000
int graph[1000][1000],g[1000][1000];//graph是各个节点之间距离,g代表邻接矩阵数组


int main()
{
	int T,N,M; 
	int u,v,w;
	int i,j,k;
	int sum;
	scanf("%d",&T);
	while(T--)
	{
		memset(g,MAX,sizeof(g));
		memset(graph,0,sizeof(graph));
		sum=0;
		scanf("%d%d",&N,&M);
	
		for(i=0;i<N;i++)
		{
			g[i][i]=0;  //令邻接矩阵对角线为0,因为结点i到结点i之间的距离为0
		}
		for(i=0;i<M;i++)
		{
			scanf("%d%d%d",&u,&v,&w);
			g[u-1][v-1]=w;   //把各个结点输入并且放入到邻接矩阵中
		}
		for(k = 0;k<N;k++)
			for(i = 0;i<N;i++)
			{
				for(j = 0;j<N;j++)
				{
					if(k == 0)
					{
						graph[i][j] =g[i][j]; //首先,当k=0的时候,就是中间结点为结点1的时候,先把graph	
					}
					else
					{
						if(graph[i][j]>(graph[i][k]+graph[k][j])) //如果D[i→k]+D[k→j]比起D[i→j]小,则可以在i,j中间插点形成最短
							graph[i][j]=graph[i][k]+graph[k][j];			
					}
				}
			
			}
		for(i=1;i<N;i++)
		{
			sum+=graph[0][i]+graph[i][0];
		}
		printf("%d\n",sum);
	}
	return 0;
}












评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值