分層圖求最短路

Ораичскевеета發表於2024-11-04

分層圖求最短路

速度限制

題目描述

在這個繁忙的社會中,我們往往不再去選擇最短的道路,而是選擇最快的路線。開車時每條道路的限速成為最關鍵的問題。不幸的是,有一些限速的標誌丟失了,因此你無法得知應該開多快。一種可以辯解的解決方案是,按照原來的速度行駛。你的任務是計算兩地間的最快路線。

你將獲得一份現代化城市的道路交通訊息。為了使問題簡化,地圖只包括路口和道路。每條道路是有向的,只連線了兩條道路,並且最多隻有一塊限速標誌,位於路的起點。兩地 $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;
}

相關文章