问题 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 ",d[des].dx,d[des].money); } return 0; }