HDOJ 3790-最短路径问题

本文介绍了一种改进的最短路径算法实现,针对存在多个评价标准(如距离和成本)的情况,通过迪杰斯特拉算法优化求解最短路径及最低成本。特别地,文章详细解释了如何在算法中同时考虑距离和成本两个因素。

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

最短路径问题

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 29796    Accepted Submission(s): 8836


题目链接:点击打开链接


Problem Description
给你n个点,m条无向边,每条边都有长度d和花费p,给你起点s终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的。
 

Input
输入n,m,点的编号是1~n,然后是m行,每行4个数 a,b,d,p,表示a和b之间有一条边,且其长度为d,花费为p。最后一行是两个数 s,t;起点s,终点。n和m为0时输入结束。
(1<n<=1000, 0<m<100000, s != t)
 

Output
输出 一行有两个数, 最短距离及其花费。


Sample Input
3 2
1 2 5 6
2 3 4 5
1 3
0 0
 


Sample Output
9 11



分析:
用floyd超时了,于是改用迪杰斯特拉,但是本题需要考虑两个点,最重要的指标是距离,如果距离相等,就要考虑花费了,所以只要算的时候顺带将花费考虑到就行,具体在代码中详细的解释。


#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
#include<stdlib.h>
#define INF 0x3f3f3f3f
using namespace std;

int Map1[1005][1005];///存放两点之间的距离
int Map2[1005][1005];///存放两点之间的花费
int n,m;   ///n个顶点,m条边
int s,t;   ///起点s,终点t
int dist[1005],cost[1005];  ///dist存放最小路径,cost存放最小花费
void Dijkstra(int v)  ///狄克斯特拉求最短路
{
    int vis[1005];    ///用来设置标记的数组
    int mindis,mincost,j,i,u;
    for(i = 1; i <= n; i++)///对dist和cost以及vis进行初始化
    {
        dist[i] = Map1[v][i];
        cost[i] = Map2[v][i];
        vis[i] = 0;
    }
    vis[v] = 1;///将原点加入已求出最短路的集合
    for(i=1;i<=n;i++)
    {
        mindis = INF;  ///另最小距离和最小花费为无穷大
        mincost = INF;
        for(j = 1; j <= n; j++)
        {
            if(vis[j] == 0)  ///如果这一点还未求出最小距离
            {
                ///如果原点到j的最小距离小于<mindis,或者等于mindis并且原点到j的最小花费<mincost,都要进行更新
                ///因为距离是最重要的指标,如果距离相等,再考虑花费小的问题
                if(dist[j]<mindis || (dist[j] == mindis && cost[j]<mincost))///
                {
                    u = j;
                    mindis = dist[j];
                    mincost = cost[j];
                }
            }
        }
        vis[u] = 1; ///将顶点u加入到已求出最短路的点集中
        for(j = 1; j <= n; j++)  ///更新dist和cost数组
            if(vis[j] == 0)  ///如果这一点没有求出最短路
            {
                if(Map1[u][j]!=INF)  ///如果u到j时有路的
                {
                    if(mindis+Map1[u][j]<dist[j])  ///加入源点到u在从u到j,比从原点直接到j的距离小
                    {
                        dist[j] = mindis+Map1[u][j];  ///更新原点到j的最小距离
                        cost[j] = mincost+Map2[u][j];  ///最小花费对应更新
                    }
                    else if(mindis+Map1[u][j]==dist[j])  ///如果两者相等
                    {
                        if(mincost+Map2[u][j]<cost[j])  ///取花费较小者
                            cost[j] = mincost + Map2[u][j];
                    }
                }
            }
    }
}
int main()
{
    int i,j,a,b,d,p;
    while(~scanf("%d%d",&n,&m))
    {
        if(n == 0 && m == 0)
            break;
       ///对图进行初始化
       for(i = 1; i <= n; i++)
            for(j = 1; j <= n; j++)
            {
                if(i == j)
                {
                    Map1[i][j] = Map2[i][j] = 0;
                }
                else
                    Map1[i][j] = Map2[i][j] = INF;
            }
        ///输入m条边
        for(i = 0; i < m; i++)
        {
            scanf("%d%d%d%d",&a,&b,&d,&p);
            if(d < Map1[a][b])///做最短路的题做多了,就知道可能两点之间有多条路
            {
                Map1[a][b] = Map1[b][a] = d;///在题目中距离因素更加重要,因此如果新输入的距离比原来的小,就更新数组的值
                Map2[a][b] = Map2[b][a] = p;
            }
        }
        scanf("%d%d",&s,&t);  ///输入起点和终点
        Dijkstra(s);          ///调用函数求最短路和最小花费
        printf("%d %d\n",dist[t],cost[t]);
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值