数据结构实验之图论七:驴友计划(Folyd算法详解)

本文介绍了一种解决寻找两点间最短路径及最小费用的算法实现,该算法能够处理多个城市的高速公路网络数据,找到从指定起点到终点的最优路径。

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

Problem Description
做为一个资深驴友,小新有一张珍藏的自驾游线路图,图上详细的标注了全国各个城市之间的高速公路距离和公路收费情况,现在请你编写一个程序,找出一条出发地到目的地之间的最短路径,如果有多条路径最短,则输出过路费最少的一条路径。
Input

连续T组数据输入,每组输入数据的第一行给出四个正整数N,M,s,d,其中N(2 <= N <= 500)是城市数目,城市编号从0~N-1,M是城市间高速公路的条数,s是出发地的城市编号,d是目的地的城市编号;随后M行,每行给出一条高速公路的信息,表示城市1、城市2、高速公路长度、收费额,中间以空格间隔,数字均为整数且不超过500,输入数据均保证有解。 

Output

在同一行中输出路径长度和收费总额,数据间用空格间隔。 

Example Input
1
4 5 0 3
0 1 1 20
1 3 2 30
0 3 4 10
0 2 2 20
2 3 1 20
Example Output
3 40
Hint
 
Author
xam 
#include<bits/stdc++.h>
#define MAX 0x3f3f3f3f

using namespace std ;

int n , m ; //顶点数,边数;
int Map[550][550] ; //点与点之间的权值;
int Money[550][550] ; //存放点与点之间的路费;
int eleco[550][550] ; //存放所有顶点到所有顶点的最短路径;
int coust[550][550] ; //存放按照点与点之间的最短路径走所需的费用;


void Forly()
{
    for(int i=0;i<n;i++) //初始化eleco和coust两个二维数组;
    {
        for(int j=0;j<n;j++)
        {
            eleco[i][j] = Map[i][j] ;
            coust[i][j] = Money[i][j] ;
        }
    }
    for(int l=0;l<n;l++) //第一个for循环提供中转值,如v0->v2=5 ,v0->v1->v2=4 ,这时经过中转值的路径小于直接到的路径。 v1是中转值; (也提供验证的作用,每个点都验证,所以循环n次,看看是否相连,因为系统和程序是抽象的,无法通过看图来判断,所以要进行验证,间接判断)
    {
        for(int i=0;i<n;i++)  
        {
            for(int j=0;j<n;j++)
            {
                if(i!=j)
                {
                    if(eleco[i][j]>eleco[i][l]+eleco[l][j]) //i直接到j的路径长度大于由i到l,再由l到j的路径长度;
                    {
                        eleco[i][j] = eleco[i][l] + eleco[l][j] ;
                        coust[i][j] = coust[i][l] + coust[l][j] ;
                    }
                    if(eleco[i][j]==eleco[i][l]+eleco[l][j]) //路径相同,选择费用最小的;
                    {
                        if(coust[i][j]>coust[i][l]+coust[l][j])
                        {
                            coust[i][j] = coust[i][l] + coust[l][j] ;
                        }
                    }
                }
            }
        }
    }
}



int main()
{
    int t ;
    scanf("%d",&t);
    while(t--)
    {
        int v0 , vn ;
        scanf("%d %d %d %d",&n,&m,&v0,&vn);
        int i , j ;
        for(i=0;i<n;i++)
        {
            for(j=0;j<n;j++)
            {
                if(i==j)
                {
                    Map[i][j] = 0 ;
                    Money[i][j] = 0 ;
                }
                else
                {
                    Map[i][j] = MAX ;
                    Money[i][j] = MAX ;
                }
            }
        }
        for(i=0;i<m;i++)
        {
            int u , v , h , k ;
            scanf("%d %d %d %d",&u,&v,&h,&k);
            Map[u][v] = Map[v][u] = h ;
            Money[u][v] = Money[v][u] = k ;
        }
        Forly();
        printf("%d %d\n",eleco[v0][vn],coust[v0][vn]);
    }
    return 0 ;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值