HDU:3790 最短路径问题

最短路径问题

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


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

解题思路:

题目中的边有双重权值,d距离,p花费,但是从题目中可以看出距离是最主要的,因为题目最后一句说,如果最短的路径有多条,则输出花费最少的一个,因此还是老方法,按最短路径去求最短路,当最短的路径长度相同的时候,再比较他们的花费,当花费比较低的时候,也要进行更新。(只是多了一点判断花费)

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
#include<stdlib.h>
#define inf 0x3f3f3f3f

using namespace std;


int Map1[1002][1002];///存放两点之间的距离
int Map2[1002][1002];///存放两点之间的花费
int n,m;   ///n个顶点,m条边
int s,t;   ///起点s,终点t
int dist[1002],cost[1002];  ///dist存放最小路径,cost存放最小花费
void Dijkstra(int v)  ///狄克斯特拉求最短路
{
    int vis[1002];    ///用来设置标记的数组
    int mindis,mincost,i,j,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,或等于,但是原点到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(dist[u]+Map1[u][j]<dist[j])  ///加入源点到u在从u到j,比从原点直接到j的距离小
                    {
                        dist[j] = dist[u]+Map1[u][j];  ///更新原点到j的最小距离
                        cost[j] = cost[u]+Map2[u][j];  ///最小花费对应更新
                    }
                    else if(dist[u]+Map1[u][j]==dist[j])  ///如果两者相等
                    {
                        if(cost[u]+Map2[u][j]<cost[j])  ///取花费较小者
                            cost[j] = cost[u] + 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;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值