D83 分层图最短路 Dijkstra 算法 HDU 6805 Deliver the Cake
D83 分层图最短路 Dijkstra 算法 HDU 6805 Deliver the Cake_哔哩哔哩_bilibili
Problem - HDU 6805 Deliver the Cake
给 n 个点 m 条无向边,每条边输入信息为:u,v,w 表示从 u 点到 v 点的边权为 w
每一个点会有一个属性 L、R 或 M,如果 u 和 v 一个为 L,另一个为 R,那么 u 和 v 之间的边权要增加 x,其他情况不变
输出从 s 点到 t 点的最短距离
思路
点的属性表达通常是拆点,每个点拆成两个点(v和v+n),分为上、下两层,
上层表示属性 L,下层表示属性 R,属性 M 表示两种属性都具备
连边时,讨论属性的排列,分为九种情况,合并两种后为七种
属性相同,层内连边,边权不变;属性不同,层间连边,边权增加 x
注意跑最短路时,把起点的两个拆点都入队,还有,答案在终点的两个拆点中找

相关板子:
D75【模板】分层图最短路 Dijkstra 算法 P4568 [JLOI2011] 飞行路线 - 董晓 - 博客园
// 分层图最短路 Dijkstra 算法 O(MlogN) #include<bits/stdc++.h> #define int long long #define pii pair<int,int> using namespace std; const int N=4e5+5,M=2e6; int h[N],idx,to[M],ne[M]; int ww[M]; void add(int u,int v,int w){ to[++idx]=v;ww[idx]=w;ne[idx]=h[u];h[u]=idx; to[++idx]=u;ww[idx]=w;ne[idx]=h[v];h[v]=idx; } int n,m,s,t; int x; char ch[N]; int d[N]; bool vis[N]; void dijkstra(){ memset(d,0x3f,sizeof d); d[s]=0; d[s+n]=0; memset(vis,0,sizeof vis); priority_queue<pii,vector<pii>,greater<pii>> q; q.push({0,s}); q.push({0,s+n}); while(!q.empty()){ auto u=q.top().second; q.pop(); if(vis[u])continue; vis[u]=1; for(int i=h[u];i;i=ne[i]){ int v=to[i]; int w=ww[i]; if(d[v]>d[u]+w){ d[v]=d[u]+w; q.push({d[v],v}); } } } } signed main(){ int T; cin>>T; while(T--){ scanf("%lld%lld%lld%lld%lld",&n,&m,&s,&t,&x); scanf("%s",ch+1); idx=0; memset(h,0,sizeof h); for(int i=0,u,v,w; i<m; i++){ scanf("%lld%lld%lld",&u,&v,&w); if((ch[u]=='L'&&ch[v]=='L')||(ch[u]=='R'&&ch[v]=='R'))add(u,v,w); else if((ch[u]=='L'&&ch[v]=='R')||(ch[u]=='R'&&ch[v]=='L'))add(u,v,x+w); else if(ch[u]=='L'&&ch[v]=='M')add(u,v,w),add(u,v+n,x+w); //v拆成v和v+n,LL,LR else if(ch[u]=='R'&&ch[v]=='M')add(u,v,x+w),add(u,v+n,w); //RL,RR else if(ch[u]=='M'&&ch[v]=='L')add(u,v,w),add(u+n,v,x+w); //LL,RL else if(ch[u]=='M'&&ch[v]=='R')add(u,v,x+w),add(u+n,v,w); //LR,RR else if(ch[u]=='M'&&ch[v]=='M')add(u,v,w),add(u,v+n,x+w), add(u+n,v,x+w),add(u+n,v+n,w); //LL,LR,RL,RR } dijkstra(); printf("%lld\n",min(d[t],d[t+n])); } }
// 分层图最短路 Dijkstra 算法 O(MlogN) #include<bits/stdc++.h> #define int long long #define pii pair<int,int> #define ipi pair<int,pii> using namespace std; const int N=1e5+5; vector<pii> e[N]; int n,m,s,t,x; char ch[N]; int d[N][2]; //0:L,1:R bool vis[N][2]; int get(char c){ if(c=='L') return 0; if(c=='R') return 1; return 2; } void dijkstra(int s){ memset(d,0x3f,sizeof d); memset(vis,0,sizeof vis); priority_queue<ipi,vector<ipi>,greater<ipi> >q; if(ch[s]=='L') q.push({d[s][0]=0,{s,0}}); else if(ch[s]=='R') q.push({d[s][1]=0,{s,1}}); else q.push({d[s][0]=0,{s,0}}),q.push({d[s][1]=0,{s,1}}); while(!q.empty()){ auto [u,p]=q.top().second; q.pop(); if(vis[u][p])continue; vis[u][p]=1; for(auto [v,w]:e[u]){ int k=get(ch[v]); if(p!=k && k!=2){ //LR,RL if(d[v][k]>d[u][p]+w+x){ d[v][k]=d[u][p]+w+x; //u,v不同时,加费走边 q.push({d[v][k],{v,k}}); } } else{ //LL,RR,LM,RM if(d[v][p]>d[u][p]+w){ d[v][p]=d[u][p]+w; //u,v相同或v不定时,定v走边 q.push({d[v][p],{v,p}}); } } } } } signed main(){ int T; cin>>T; while(T--){ scanf("%lld%lld%lld%lld%lld",&n,&m,&s,&t,&x); scanf("%s",ch+1); for(int i=1; i<=n; i++) e[i].clear(); for(int i=1,u,v,w; i<=m; i++){ scanf("%lld%lld%lld",&u,&v,&w); e[u].push_back({v,w}); e[v].push_back({u,w}); } dijkstra(s); printf("%lld\n",min(d[t][0],d[t][1])); } }
浙公网安备 33010602011771号