D74 最短路 化层为点 Dijkstra 算法 HDU4725 The Shortest Path in Nya Graph

D74 最短路 化层为点 Dijkstra 算法 HDU4725 The Shortest Path in Nya Graph_哔哩哔哩_bilibili

 

Problem - HDU4725 The Shortest Path in Nya Graph

给 n 个点 m 条有权边的无向图,给出每个点所属的层,相邻的层之间有一条权值为 c 的边,求 1-n 的最短路。

思路

扩点:把每一层化为一个虚点

扩边:

  1. 每层虚点向每层的实点连权值为 0 的单向边;
  2. 每个实点向相邻层虚点连权值为 c 的单向边。

这样虚点就架起了相邻层之间的一座代价为 c 的桥。

然后,实点之间连接 m 条双向边。跑一遍 Dijkstra 求最短路。

图中,黑点为实点,黑边为双向边;红点为虚点,红边为单向边。

           image

相关板子:

D02【模板】最短路 Dijkstra 算法 P4779 单源最短路径 - 董晓 - 博客园

 

// 最短路 Dijkstra 算法 O(mlogn)
#include<bits/stdc++.h>
#define pii pair<int,int>
using namespace std;

const int N=100010,inf=0x3f3f3f3f;
int idx,h[N*2],to[N*5],ne[N*5],w[N*5];
void add(int x,int y,int z){
  to[++idx]=y;w[idx]=z;ne[idx]=h[x];h[x]=idx;
}
int n,m,c;
int d[N*2],vis[N*2];

void dijkstra(){
  for(int i=1;i<=2*n;i++)d[i]=inf,vis[i]=0;
  d[1]=0;
  priority_queue<pii,vector<pii>,greater<pii>> q;
  q.emplace(0,1);
  while(!q.empty()){
  int 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];
      if(d[v]>d[u]+w[i]){
        d[v]=d[u]+w[i];
        q.emplace(d[v],v);
      }
    }
  }
}
int main(){
  int T,cas=0;
  scanf("%d",&T);
  while(T--){
    idx=0;
    memset(h,0,sizeof(h));
    scanf("%d%d%d",&n,&m,&c);
    for(int i=1,x;i<=n;i++){
      scanf("%d",&x); //实点i在第x层
      add(n+x,i,0);   //第x层虚点向实点i连权值为0的单向边
      if(x>1) add(i,n+(x-1),c); 
      if(x<n) add(i,n+x+1,c); //实点i向相邻层虚点连权值为c的单向边
    }
    for(int i=1,u,v,w;i<=m;i++){
      scanf("%d%d%d",&u,&v,&w);
      add(u,v,w); add(v,u,w); //实点之间连双向边
    }
    
    dijkstra();
    printf("Case #%d: ",++cas);
    if(d[n]==inf) printf("-1\n");
    else printf("%d\n",d[n]);
  }
}

 

posted @ 2026-02-15 22:11  董晓  阅读(29)  评论(0)    收藏  举报