题目描述
在这个繁忙的社会中,我们往往不再去选择最短的道路,而是选择最快的路线。开车时每条道路的限速成为最关键的问题。不幸的是,有一些限速的标志丢失了,因此你无法得知应该开多快。一种可以辩解的解决方案是,按照原来的速度行驶。你的任务是计算两地间的最快路线。
你将获得一份现代化城市的道路交通信息。为了使问题简化,地图只包括路口和道路。每条道路是有向的,只连接了两条道路,并且最多只有一块限速标志,位于路的起点。两地 A 和 B,最多只有一条道路从 A 连接到 B。你可以假设加速能够在瞬间完成并且不会有交通堵塞等情况影响你。当然,你的车速不能超过当前的速度限制。
输入格式
第一行是 3 个整数 N,M 和 D (2≤N≤150),表示道路的数目,用 N−1 标记。M 是道路的总数,D 表示你的目的地。
接下来的 M 行,每行描述一条道路,每行有 4 个整数 A (0≤A<N),B (0≤B<N),V (0≤V≤500) 和 L (1≤L≤500),这条路是从 A 到 B 的,速度限制是 V,长度为 L。如果 V 是 0,表示这条路的限速未知。
如果 V 不为 0,则经过该路的时间 T=VL。否则 T=VoldL,VoldVold 是你到达该路口前的速度。开始时你位于 0 点,并且速度为 70。
输出格式
输出文件仅一行整数,表示从 00 到 D 经过的城市。
输出的顺序必须按照你经过这些城市的顺序,以 00 开始,以 D 结束。仅有一条最快路线。
输入输出样例
输入 #1复制
6 15 1 0 1 25 68 0 2 30 50 0 5 0 101 1 2 70 77 1 3 35 42 2 0 0 22 2 1 40 86 2 3 0 23 2 4 45 40 3 1 64 14 3 5 0 23 4 1 95 8 5 1 0 84 5 2 90 64 5 3 36 40
输出 #1复制
0 5 2 3 1
解析:
这时一道这么在最小时间内到达D点的题。
我们可以想到最短路算法,迪杰斯特拉算法。每次枚举其速度,这个通道的时间即可。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define N 200005
int n, m, d;
int first[N], Next[N], to[N], sp[N], len[N], tot;
double dis[205][1005];
int vis[205][1005];
pair<int, int> from[205][1005];
void add(int x, int y, int z, int zz)
{
Next[++tot] = first[x];
first[x] = tot;
to[tot] = y;
sp[tot] = z;
len[tot] = zz;
return;
}
void dijkstrar(int x)
{
priority_queue<pair<double, pair<int, int> > > q;
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= 505; j++)
{
dis[i][j] = 1e9;
vis[i][j] = 0;
}
}
dis[x][70] = 0;
q.push(make_pair(0, make_pair(x, 70)));
while(!q.empty())
{
pair<int, int> u = q.top().second;
q.pop();
if(vis[u.first][u.second])
{
continue;
}
vis[u.first][u.second] = 1;
for(int i = first[u.first]; i; i = Next[i])
{
int v = to[i], sped = (sp[i] ? sp[i] : u.second);
double time = (double)len[i] / (double)sped;
if(dis[u.first][u.second] + time < dis[v][sped])
{
dis[v][sped] = dis[u.first][u.second] + time;
from[v][sped] = u;
q.push(make_pair(-dis[v][sped], make_pair(v, sped)));
}
}
}
return;
}
void write(int x, int v)
{
if(x == 1)
{
printf("0 ");
return;
}
write(from[x][v].first, from[x][v].second);
printf("%d ", x - 1);
return;
}
int main()
{
cin >> n >> m >> d;
int x,y,zz,z;
for(int i = 1;i <= m;i++)
{//从 1开始到 n
cin >> x>> y >> z>> zz; // x -> y 速度为z 限速为zz
x++;
y++;
add(x,y,z,zz);
}
dijkstrar(1);
d++;
int maxx = 0;
dis[d][maxx] = 1e9;
for(int i = 1;i <= 500;i++)//遍历一边速度
{
if(dis[d][i] < dis[d][maxx]) // dis为时间
{
maxx = i;
}
}
write(d,maxx);
return 0;
}
时间复杂度:O(n*m);