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;
}