327 最短路径 C语言

327 最短路径 C语言

  • 问题描述

    求图中任意两个顶点之间的最短路径。

  • 输入格式

    输入数据第一行是一个正整数,表示图中的顶点个数n(顶点将分别按0,1,…,n-1进行编号)。之后的n行每行都包含n个整数,第i行第j个数表示顶点i-1和顶点j-1之间的边长,用10000来表示两个顶点之间无边。后面每行2个数字,表示一对待求最短路径的顶点,用-1 -1表示输入结束,-1 -1不求解。

  • 输出格式
    每对待求最短路径的顶点输出两行数据:第一行输出两个顶点间的最短路径长度,第二行输出最短路径,要按顺序输出顶点编号序列,顶点间用空格隔开。当两个顶点间没有路径时,只在一行上输出字符串“NO”。

  • 样例输入

    7
    0 12 10000 10000 10000 10000 10000
    12 0 10000 10000 3 10000 10000
    10000 10000 0 10000 10000 21 11
    10000 10000 10000 0 10000 10000 10000
    10000 3 10000 10000 0 10000 8
    10000 10000 21 10000 10000 0 10000
    10000 10000 11 10000 8 10000 0
    0 2
    0 3
    5 0
    2 1
    1 5
    -1 -1

  • 样例输出

    34
    0 1 4 6 2
    NO
    55
    5 2 6 4 1 0
    22
    2 6 4 1
    43
    1 4 6 2 5

  • 解题思路

    运用弗洛伊德算法求解

  • 完整代码

#include<stdio.h>
int main()
{
	int n,i,j,k,num1,num2,top;
	int D[100][100],Path[100][100],Stack[100];
	/*D存储的是结点间最短路径长度
	Path存储的是最短路径中结点的前驱结点:比如1->3的最短路径是1 6 4 2 3,则Path[1][3]=2,Path[1]      [2]=4,Path[1][4]=6,Path[1][6]=1.
	Stack作为栈,便于输出最短路径  */
	top=-1;
	scanf("%d",&n);
	for(i=0;i<n;i++){//各对节点之间初始已知路径及距离
		for(j=0;j<n;j++)
		{
			scanf("%d",&D[i][j]);
			if(D[i][j]<1000)//从i到j之间有直接路径
			 Path[i][j]=i;
			else Path[i][j]=-1;
		}
	}
	for(k=0;k<n;k++)//加入结点k
		for(i=0;i<n;i++)
			for(j=0;j<n;j++)
			{
				if(D[i][j]>D[i][k]+D[k][j])//从i到k再到j的路径更短
				{
					D[i][j]=D[i][k]+D[k][j];//更新路径
					Path[i][j]=Path[k][j];//j的前驱结点改为k
				}
			}
	while(scanf("%d %d",&num1,&num2)!=EOF&&num1!=-1&&num2!=-1)
	{

		if(Path[num1][num2]==-1)//没有通路
		{
			printf("No");
			printf("\n");
		}
		else //有通路
		{
			printf("%d",D[num1][num2]);//输出路径长度
			printf("\n");
			j=num2;
			while(Path[num1][j]!=num1)//当j的前驱结点不等于起点时,即中间路径已经走完
			{
				top++;
				Stack[top]=Path[num1][j];//将数据存到栈里,因为是从终点到起点倒着走的
				j=Path[num1][j];
			}
			printf("%d ",num1);
			while(top!=-1)
			{
				printf("%d ",Stack[top]);//弹栈
				top--;
			}
			printf("%d\n",num2);
		}
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一——一

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值