P4568 JLOI 飛行路線 分層最短路板子
阿新 • • 發佈:2020-07-28
luogu SuperJvRuo的圖
各層內部正常連邊,各層之間從上到下連權值為0的邊。每向下跑一層,就相當於免費搭一次飛機。跑一遍從\(s\)到\(t+n∗k\)的最短路即可。
#include<cstdio> #include<queue> #include<iostream> #include<cstring> #define maxn 5000005 #define maxm 1000005 using namespace std; int n,m,k,s,t,tot,ans = 0x7777777f,head[maxn],dis[maxn]; bool vis[maxn]; inline int read() { int x = 0,f = 1; char s = getchar(); while(s < '0' || s > '9') {if(s == '-') f = -1;s = getchar();} while(s >= '0' && s <= '9') {x = x * 10 + s - '0';s = getchar();} return f * x; } inline int min(int a,int b){return a < b ? a : b;} struct edge{ int to,next,dis; }e[maxm<<3]; struct node{ int val,id; }; inline bool operator<(node x,node y){return x.val > y.val;} inline void add(int u,int v,int val){ e[++tot].to = v; e[tot].dis = val; e[tot].next = head[u]; head[u] = tot; } inline void dijkstra(int s) {//堆優化 dijkstra memset(dis, 0x7f, sizeof (dis)); priority_queue<node> q; dis[s] = 0; q.push((node) { 0, s }); while(!q.empty()) { int u = q.top().id; q.pop(); if (vis[u]) continue; vis[u] = 1; for (int v, w, i = head[u]; v = e[i].to, w = e[i].dis, i; i = e[i].next) if (dis[v] > dis[u] + w) { dis[v] = dis[u] + w; if (!vis[v]) q.push((node) { dis[v], v }); } } } int main(){ n=read();m=read();k=read();s=read();t=read(); s ++,t ++; int u,v,w; for(int i = 1;i <= m;i++){ u=read();v=read();w=read(); ++ u; ++ v; add(u,v,w); add(v,u,w); for(int j = 1;j <= k;j++){ add(u + (j - 1) * n, v + j * n, 0), add(v + (j - 1) * n, u + j * n, 0); //層與層之間對應的點連一條權值為 0 的邊 add(u + j * n, v + j * n, w), add(v + j * n, u + j * n, w);} //每一層中對應的點連邊 } dijkstra(s); for(int i = 0;i <= k;i++) ans = min(ans,dis[t + i*n]); printf("%d\n",ans); return 0; }