关于最短路径的弗洛伊德算法(floyd)pku1125解题报告

本文详细介绍了Floyd算法在解决含有n个顶点的带权有向图中,求每对顶点之间的最短路径和路径长度的方法。通过逐步迭代更新路径权重,最终得出每对顶点间最短路径及其长度。使用实例代码演示了算法实现过程,包括边界条件处理和路径优化。此外,文章还提供了关键代码片段,以便读者理解并应用Floyd算法于实际问题中。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

弗洛伊德算法是求最小路径的很好算法,但算法要求的时间复杂度很高,当结点少得时候可以用:

问题描述:已知一个含有n个顶点的各边权值均大于0的带权有向图,对每对顶点vi!=vj,要求求出每一对顶点之间的最短路径和最短路径长度。 
解决方案:弗洛伊德(floyd)算法

A0
1
2
3
A1
1
2
3
1
0
4
5
1
0
4
5
2
2
0
6
2
2
0
min(6,2+5)
3
2
2
0
3
2
min(2,2+4)
0

A2
1
2
3
A3
1
2
3
1
0
4
min(5,4+6)
1
0
min(4,5+2)
5
2
2
0
6
2
min(2,6+2)
0
6
3
min(2,2+2)
2
0
3
2
2
0

这里的Ai即为用i做中间量时,x到y的最短路径(最小值),如A1即为当用1做中间值时,2-3,3-2的最小值,这样当运行到A3时,每个x到每个y的最短路径都以求出来了,这时,每行中的最大值即为该行算代表的数走完全部支点的值(当为无穷大时(这里无穷取1200即可),说明走不通),在把每行最大值求最小值,即为问题解。

核心代码:

for(int k=1;k<=n;k++) //生成A0,A1,A2...的循环
         for(int i=1;i<=n;i++) //
            for(int j=1;j<=n;j++) //
                //如果是i==k||j==k||i==j就保持不变,否则取最小值
                array[i][j]=(i==k||j==k||i==j)?array[i][j]:
((array[i][j]<(array[i][k]+array[k][j])?array[i][j]:(array[i][k]+array[k][j])));

最后根据题意,取每行最大值中的最小值即可。

注意:要把对角线上的数值进行特殊处理,把它们都至为0.而走不到的就置为1200。

代码:

#include<stdio.h>
#include<memory.h>
main(){
int i,n;
int a[101][101],max,m[101],flag,j,k,a1,n1,b;
int min;
while(scanf("%d",&n)&&n){
   for(i=1;i<=n;i++)
    for(j=1;j<=n;j++)
     a[i][j]=(i==j)?0:-1;          //出对角线外,其它都只为-1,对角线值为0;
   for(i=1;i<=n;i++){
    scanf("%d",&n1);
    while(n1--){
     scanf("%d%d",&a1,&b);
     a[i][a1]=b;
    }
   } 
   for(k=1;k<=n;k++){
    for(j=1;j<=n;j++)
     if(a[k][j]==-1) 
      a[k][j]=1200;             //两点之间没有路径,则值置为1200(无穷大的意思);
   }
   for(i=1;i<=n;i++)
    for(k=1;k<=n;k++)
     for(j=1;j<=n;j++)
      a[k][j]=(i==k||i==j||k==j)?a[k][j]:((a[k][j]<(a[k][i]+a[i][j])?a[k][j]:(a[k][i]+a[i][j])));     //floyd的模板代码
   for(i=1;i<=n;i++){
    max=0;
    for(j=1;j<=n;j++)
     max=max>a[i][j]?max:a[i][j];
    m[i]=max;
   }
   flag=0;
   min=1200;
   for(i=1;i<=n;i++){

    if(min>m[i]){
     min=m[i];
     flag=i;
    }
   }
   if(flag)
    printf("%d %d/n",flag,min);
   else
    printf("disjoint/n");
}
return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值