问题 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;
}