D78 分层图最短路 Dijkstra 算法 CF1915G Bicycles
D78 分层图最短路 Dijkstra 算法 CF1915G Bicycles_哔哩哔哩_bilibili
思路
问题是求最短路,花费由点权和边权乘积决定,到一个点时,点权(即速度)可换可不换
到达每一个点的决策有两种可能性:
- 不换速度,以原速度继续前进
- 换当前点上的速度,继续前进
考虑分层图最短路,按速度($\le1000$)分层,每到达一个点,根据是否换速度做两次松弛更新
d[i][j] 表示到达点 i 使用速度 j 的最小花费

优化:根据贪心思想,到达一个点时,如果该点的速度更小,就只更新该速度的状态;如果原速度更小,就只更新原速度的状态
相关板子:
D75【模板】分层图最短路 Dijkstra 算法 P4568 [JLOI2011] 飞行路线 - 董晓 - 博客园
// 分层图最短路 Dijkstra 算法 O(mk*log(nk)) #include<bits/stdc++.h> using namespace std; const int N=1005; int h[N],idx,to[N<<1],ne[N<<1],w[N<<1]; void add(int x,int y,int z){ to[++idx]=y,w[idx]=z,ne[idx]=h[x],h[x]=idx; } struct node{ long long d; int v,s; //花费,点,速度 bool operator<(const node &b)const&{ return d>b.d; } }; int n,m,a[N]; long long d[N][N]; //d[i][j]表示到点i使用速度j的最小花费 void dijkstra(){ memset(d,0x3f,sizeof d); d[1][a[1]]=0; priority_queue<node> q; q.push({0,1,a[1]}); while(!q.empty()){ auto [dd,u,s]=q.top();q.pop(); if(dd!=d[u][s])continue; for(int i=h[u];i;i=ne[i]){ int v=to[i]; long long ww=1ll*s*w[i]; //花费 if(d[v][s]>d[u][s]+ww){ //不换速度 d[v][s]=d[u][s]+ww; q.push({d[v][s],v,s}); } if(d[v][a[v]]>d[u][s]+ww){ //换速度 d[v][a[v]]=d[u][s]+ww; q.push({d[v][a[v]],v,a[v]}); } } } } int main(){ int t; cin>>t; while(t--){ cin>>n>>m; idx=0; memset(h,0,sizeof h); for(int i=1,u,v,w;i<=m;i++){ cin>>u>>v>>w; add(u,v,w);add(v,u,w); } for(int i=1;i<=n;i++)cin>>a[i]; //速度 dijkstra(); long long ans=1e18; for(int i=1;i<=n;i++)ans=min(ans,d[n][a[i]]); cout<<ans<<"\n"; } }
// 分层图最短路 Dijkstra 算法 O(mk*log(nk)) #include<bits/stdc++.h> using namespace std; const int N=1005; int h[N],idx,to[N<<1],ne[N<<1],w[N<<1]; void add(int x,int y,int z){ to[++idx]=y,w[idx]=z,ne[idx]=h[x],h[x]=idx; } struct node{ long long d; int v,s; //花费,点,速度 bool operator<(const node &b)const&{ return d>b.d; } }; int n,m,a[N]; long long d[N][N]; //d[i][j]表示到点i使用速度j的最小花费 void dijkstra(){ memset(d,0x3f,sizeof d); d[1][a[1]]=0; priority_queue<node> q; q.push({0,1,a[1]}); while(!q.empty()){ auto [dd,u,s]=q.top();q.pop(); if(dd!=d[u][s])continue; for(int i=h[u];i;i=ne[i]){ int v=to[i]; long long ww=1ll*s*w[i]; //花费 int sp=min(s,a[v]); //贪心最小速度 if(d[v][sp]>d[u][s]+ww){ d[v][sp]=d[u][s]+ww; q.push({d[v][sp],v,sp}); } } } } int main(){ int t; cin>>t; while(t--){ cin>>n>>m; idx=0; memset(h,0,sizeof h); for(int i=1,u,v,w;i<=m;i++){ cin>>u>>v>>w; add(u,v,w);add(v,u,w); } for(int i=1;i<=n;i++)cin>>a[i]; //速度 dijkstra(); long long ans=1e18; for(int i=1;i<=n;i++)ans=min(ans,d[n][a[i]]); cout<<ans<<"\n"; } }
浙公网安备 33010602011771号