ACM程序设计选修课——Problem F:(ds:图)旅游规划(优先队列+SPFA)

 

问题 F: (ds:图)旅游规划

时间限制: 1 Sec   内存限制: 128 MB
提交: 14   解决: 4

题目描述

有了一张自驾旅游路线图,你会知道城市间的高速公路长度、以及该公路要收取的过路费。现在需要你写一个程序,帮助前来咨询的游客找一条出发地和目的地之间的最短路径。如果有若干条路径都是最短的,那么需要输出最便宜的一条路径。

输入

 

 

 

 

 

第一行为整数T,表示有T个case(测试实例)。

接下来每个case包含:

第1行给出4个正整数N、M、S、D,其中N(2<=N<=500)是城市的个数,顺便假设城市的编号为0~(N-1);M是高速公路的条数;S是出发地的城市编号;D是目的地的城市编号。随后的M行中,每行给出一条高速公路的信息,分别是:城市1、城市2、高速公路长度、收费额,中间用空格分开,数字均为整数且不超过500。输入保证解的存在。

输出

在一行里输出路径的长度和收费总额,数字间以空格分隔,输出结尾不能有多余空格。

样例输入

2
4 5 0 3
0 1 1 20
1 3 2 30
0 3 4 10
0 2 2 20
2 3 1 20
2 1 0 1
1 0 2 3

样例输出

3 40
2 3

 

 

苦于寻找如何对两个边权进行最短路的计算,无数次WA后总算是知道了。思路:首先正常合并当前边,然后若临时距离等于永久距离之和,则比较费用,若费用小则将费用变化一下。另外一个好处就是由于是搜索全部关联边,因此不用担心重边的问题

代码:

#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<sstream>
#include<cstring>
#include<cstdio>
#include<string>
#include<deque>
#include<stack>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#define INF 0x3f3f3f3f
#define MM(x) memset(x,0,sizeof(x))
using namespace std;
typedef long long LL;
struct info
{
    int dx;
    int money;
};
 
info d[550];
vector<pair<int,info> >que[550];
 
int main(void)
{  
    int tcase;
    int n,m,i,j,x,y,z,s,t,des;
    scanf("%d",&tcase);
    while (tcase--)
    {
        for (i=0; i<550; i++)
            que[i].clear();
        memset(d,INF,sizeof(d));
        scanf("%d%d%d%d",&n,&m,&s,&des);    
        info one;
        for (i=0; i<m; i++)
        {
            scanf("%d%d%d%d",&x,&y,&one.dx,&one.money);
            que[x].push_back(make_pair(y,one));
            que[y].push_back(make_pair(x,one));
        }
        priority_queue<pair<int,int> >Q;
        while (!Q.empty())
            Q.pop();  
        d[s].dx=0;
        d[s].money=0;
        Q.push(make_pair(-d[s].dx,s));
        while (!Q.empty())
        {
            int now=Q.top().second;
            Q.pop();
            for (i=0; i<que[now].size(); i++)
            {
                int v=que[now][i].first;
                if(d[v].dx>d[now].dx+que[now][i].second.dx)
                {
                    d[v].dx=d[now].dx+que[now][i].second.dx;
                    d[v].money=d[now].money+que[now][i].second.money;
                    Q.push(make_pair(-d[v].dx,v));
                }
                else if(d[v].dx==d[now].dx+que[now][i].second.dx&&d[v].money>d[now].money+que[now][i].second.money)
                	d[v].money=d[now].money+que[now][i].second.money;
            }
        }   
        printf("%d %d\n",d[des].dx,d[des].money);
    }
    return 0;
}

转载于:https://www.cnblogs.com/Blackops/p/5766345.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值