The Shortest Path in Nya Graph

hdu4725:http://acm.hdu.edu.cn/showproblem.php?pid=4725

题意:给你一张无向图,然后这些点会分在不同的层中,相邻的层的任意两点之间的距离是c。然后还有一些额外边,有相应的边权,现在求1--n的最短距离。

题解:如果直接建图的话,会发现边的数量实在是太多了。所以这样朴素的建图方式肯定不行。于是,要加入一些点。怎么加呢?每一层加入两个点,,第i层加入的两个点是 n+i,和n+n+i,如果第u属于第i层,则需要建立两条有向边,u-->n+i;i+2*n--->u,同时第i层和i+1层之间建边,i+n--->i+1+2*n;i+n+1----->i+2*n;然后跑最短路,可能是这一题的边比较多,所以用spfa一直T,于是改用dijkstar加优先队列优化。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<vector>
 6 #include<queue>
 7 #define inf 1000000000+100
 8 using namespace std;
 9 const int N=3e5+10;
10 const int M=1e6+5e5;
11 int n,m,c,u,v,w;
12 struct Node{
13   int v;
14   int next;
15   int w;
16 }edge[M];
17 struct Edge{
18   int u;
19   int w;
20   bool operator<(const Edge a) const{
21     return w>a.w;
22   }
23 };
24 int head[N],cnt,dist[N];
25 bool vis[N];
26 void init(){
27   memset(head,-1,sizeof(head));
28   cnt=0;
29 }
30 
31 void add(int u,int v,int w){
32    edge[cnt].v=v;
33    edge[cnt].next=head[u];
34    edge[cnt].w=w;
35    head[u]=cnt++;
36 }
37 int spfa(){
38     for(int i=1;i<=3*n;i++){
39         dist[i]=inf;
40         vis[i]=0;
41     }
42    priority_queue<Edge>Q;
43    vis[1]=1;
44    dist[1]=0;
45    Edge temp;temp.u=1;temp.w=0;
46    Q.push(temp);
47    while(!Q.empty()){
48        temp=Q.top();
49         Q.pop();
50         int u=temp.u;
51         vis[u]=0;
52         for(int i=head[u];i!=-1;i=edge[i].next){
53             int v=edge[i].v;
54             if(dist[v]>edge[i].w+dist[u]){
55                 dist[v]=edge[i].w+dist[u];
56                 if(!vis[v]){
57                     vis[v]=1;
58                   temp.u=v;temp.w=dist[v];
59                     Q.push(temp);
60                 }
61             }
62         }
63 
64    }
65    return dist[n];
66 }
67 int main(){
68      int T,tt=1;
69      scanf("%d",&T);
70      while(T--){
71         scanf("%d%d%d",&n,&m,&c);
72         init();
73         for(int i=1;i<=n;i++){
74             scanf("%d",&u);
75             add(i,u+n,0);
76             add(u+2*n,i,0);
77         }
78         for(int i=1;i<n;i++){
79           add(i+n,i+n*2+1,c);
80           add(i+n+1,i+2*n,c);
81         }
82       for(int i=1;i<=m;i++){
83         scanf("%d%d%d",&u,&v,&w);
84         add(u,v,w);
85         add(v,u,w);
86       }
87       int ans=spfa();
88       if(n==0)ans=inf;
89       if(n==1)ans=0;
90       if(ans==inf)printf("Case #%d: -1
",tt++);
91       else
92       printf("Case #%d: %d
",tt++,ans);
93      }
94 }
View Code
原文地址:https://www.cnblogs.com/chujian123/p/3925191.html