分層圖求最短路
速度限制
題目描述
在這個繁忙的社會中,我們往往不再去選擇最短的道路,而是選擇最快的路線。開車時每條道路的限速成為最關鍵的問題。不幸的是,有一些限速的標誌丟失了,因此你無法得知應該開多快。一種可以辯解的解決方案是,按照原來的速度行駛。你的任務是計算兩地間的最快路線。
你將獲得一份現代化城市的道路交通訊息。為了使問題簡化,地圖只包括路口和道路。每條道路是有向的,只連線了兩條道路,並且最多隻有一塊限速標誌,位於路的起點。兩地 $A$ 和 $B$,最多隻有一條道路從 $A$ 連線到 $B$。你可以假設加速能夠在瞬間完成並且不會有交通堵塞等情況影響你。當然,你的車速不能超過當前的速度限制。
輸入格式
第一行是 $3$ 個整數 $N$,$M$ 和 $D$($2\leq N\leq 150$,$1\leq M\leq 22500$),表示道路的數目,用 $0 \sim N-1$ 標記。$M$ 是道路的總數,$D$ 表示你的目的地。
接下來的 $M$ 行,每行描述一條道路,每行有 $4$ 個整數 $A$($0\leq A<N$),$B$($0\leq B<N$),$V$ ($0\leq V\leq 500$)和 $L$($1\leq L\leq 500$),這條路是從 $A$ 到 $B$ 的,速度限制是 $V$,長度為 $L$。如果 $V$ 是 $0$,表示這條路的限速未知。
如果 $V$ 不為 $0$,則經過該路的時間 $T=\frac{L}{V}$。否則 $T=\frac{L}{\text{Vold}}$,$\text{Vold}$ 是你到達該路口前的速度。開始時你位於 $0$ 點,並且速度為 $70$。
輸出格式
輸出檔案僅一行整數,表示從 $0$ 到 $D$ 經過的城市。
輸出的順序必須按照你經過這些城市的順序,以 $0$ 開始,以 $D$ 結束。僅有一條最快路線。
樣例 #1
樣例輸入 #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
考慮分層圖。
建陣列$dis[i][j]$表示從出發點到$i$點,速度為$j。vis[i][j]$表示從出發點到$i$,速度為$j$是否訪問過。
為得到最短的路線,可以建一個$from[i][j]$陣列,表示從出發點到$i$,速度為$j$的最短路的上一個點。最後跑一遍堆最佳化的$dijkstra$即可。
#include<bits/stdc++.h>
using namespace std;
const int N=160,M=510;
struct Node{
int to,v;
double l;
Node(int to=0,int v=0,double l=0):to(to),v(v),l(l) {}
};
int n,m,t;
double dis[N][M];
pair<int,int> lst[N][M];
int vis[N][M];
vector<Node> g[N];
vector<int> ans;
void bfs(){ //dijkstra
for(int i=1;i<=n;i++){
for(int j=1;j<=M;j++) dis[i][j]=2e9;
}
dis[1][70]=0;
priority_queue<pair<double,pair<int,int> > > pq;
pq.emplace(0,make_pair(1,70));
while(!pq.empty()){
int u=pq.top().second.first;
int o=pq.top().second.second;
pq.pop();
if(vis[u][o]) continue;
vis[u][o]=1;
for(auto v:g[u]){
if(v.v&&dis[v.to][v.v]>dis[u][o]+v.l/v.v){ //有速度限制
dis[v.to][v.v]=dis[u][o]+v.l/v.v;
lst[v.to][v.v]=make_pair(u,o);
pq.emplace(make_pair(-dis[v.to][v.v],make_pair(v.to,v.v)));
}
if(!v.v&&dis[v.to][o]>dis[u][o]+v.l/o){ //無速度限制
dis[v.to][o]=dis[u][o]+v.l/o;
lst[v.to][o]=make_pair(u,o);
pq.emplace(make_pair(-dis[v.to][o],make_pair(v.to,o)));
}
}
}
}
int main(){
scanf("%d%d%d",&n,&m,&t);
t++;
for(int i=1;i<=m;i++){
int u,v,l,d;
scanf("%d%d%d%d",&u,&v,&l,&d);
u++;v++;
g[u].emplace_back(v,l,d);
}
bfs();
pair<int,int> now;
double maxn=2e9;
for(int i=1;i<M;i++){
if(dis[t][i]<maxn){
maxn=dis[t][i];
now=make_pair(t,i);
}
}
while(now.first){
ans.push_back(now.first-1);
now=lst[now.first][now.second];
}
reverse(ans.begin(),ans.end());
// reverse(ans.begin(),ans.back());
for(auto v:ans) printf("%d ",v);
return 0;
}