The Shortest Path in Nya Graph HDU - 4725

题目链接:https://vjudge.net/problem/HDU-4725

题意:附上一张图吧,把题目的意思画出来,我本来是按照上面的图建图,以为层节点和层上的节点无向就OK了,然后看了别人的代码发现层结点和相邻的层的点都无向,

然后想到一个样例就是我上面图无法解决的,我把权值和走的边都标出来了,就比较形象,于是去了一行代码加上两行代码就可以过了。

核心思想就是把每层抽象为一个层节点,层节点到该层的所有点权值为0,就可以了,再加上“层结点和相邻的层的点都无向”,加上点之间的无向边就可以直接跑图了,

当然,因为点太多O(n^2)已经无法满足了,所有要dijkstra加上堆优化,使得复杂度降到O(nlogn)。

层节点放在(n + u)个节点上,代码有注释。


  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 #include <queue>
  6 #include <cmath>
  7 #include <iomanip>
  8 using namespace std;
  9 
 10 typedef long long LL;
 11 #define inf (1LL << 29) - 1
 12 #define rep(i,j,k) for(int i = (j); i <= (k); i++)
 13 #define rep__(i,j,k) for(int i = (j); i < (k); i++)
 14 #define per(i,j,k) for(int i = (j); i >= (k); i--)
 15 #define per__(i,j,k) for(int i = (j); i > (k); i--)
 16 
 17 const int N = 100010 * 10;
 18 int n,m,C;
 19 int head[N];
 20 int dis[N];//最短路数组
 21 int app[N]; //存节点存在于第几层
 22 bool vis[N];
 23 int cnt;//链式前向星
 24 struct Edge{
 25 
 26     int to;
 27     int next;
 28     int w;
 29 }edge[N];
 30 
 31 struct Node{
 32     int num;
 33     int W;
 34 
 35     bool friend operator<(Node a,Node b){
 36         return a.W > b.W;
 37     }
 38 };
 39 
 40 void add(int u,int v,int w){
 41 
 42     edge[cnt].to = v;
 43     edge[cnt].w = w;
 44     edge[cnt].next = head[u];
 45     head[u] = cnt++;
 46 }
 47 
 48 //接下来直接是裸的(dijkstra + 优先队列优化)
 49 void dijkstra(){
 50 
 51     rep(i,1,n + n) vis[i] = 0;
 52     rep(i,1,n + n) dis[i] = inf;
 53 
 54     priority_queue<Node> que;
 55     que.push(Node{1,0});
 56     dis[1] = 0;
 57 
 58     while(!que.empty()){
 59 
 60         Node tmp = que.top();   
 61         que.pop();
 62         int u = tmp.num;
 63         if(!vis[u]){
 64             vis[u] = true;
 65 
 66             for(int j = head[u]; ~j; j = edge[j].next){
 67                 
 68                 int v = edge[j].to;
 69                 int w = edge[j].w;
 70                 if(!vis[v] && dis[v] > dis[u] + w){
 71                     dis[v] = dis[u] + w;
 72                     que.push(Node{v,dis[v]});
 73                 }
 74                     
 75             }
 76         }
 77     }
 78 }
 79 
 80 int main(){
 81     
 82     ios::sync_with_stdio(false);
 83     cin.tie(0);
 84 
 85     int T;
 86     cin >> T;
 87 
 88     rep(p,1,T){
 89 
 90         cin >> n >> m >> C;
 91 
 92         rep(i,1,n + n) head[i] = -1;
 93         rep(i,1,n + n) app[i] = -1;
 94         cnt = 1;
 95         rep(i,1,n){ //第几个点
 96             int u;
 97             cin >> u; //属于第几层
 98             add(n + u,i,0); //第u层上加了到第i个点的边,权值为0
 99             // add(i,n + u,0);
100             app[i] = u;
101         }
102 
103         //相邻层点无向边权值为C
104         rep__(i,n + 1,n + n){
105             //相邻层都存在
106             if(head[i] != -1 && head[i + 1] != -1){
107                 add(i,i + 1,C);
108                 add(i + 1,i,C);
109             }              
110         }
111 
112         //层节点和相邻层的节点进行无向
113         rep(i,1,n){
114             if(app[i] == -1) continue;
115             //下面第二个判断,判断该层是否存在
116             if(app[i] > 1) if(head[n + app[i] - 1] != -1) add(i,n + app[i] - 1,C);
117             if(app[i] < n) if(head[n + app[i] + 1] != -1) add(i,n + app[i] + 1,C);
118         }
119 
120         //点之间的无向边
121         int u,v,w;
122         rep(i,1,m){
123         
124             cin >> u >> v >> w;
125             add(u,v,w);
126             add(v,u,w);
127         }
128 
129 
130         dijkstra();
131         cout << "Case #" << p << ": ";
132         if(dis[n] == inf) cout << "-1" << endl;
133         else cout << dis[n] << endl;
134     }
135 
136 
137     getchar();getchar();
138 
139     return 0;
140 }

 

posted @ 2019-07-25 21:48  SummerMingQAQ  阅读(206)  评论(0编辑  收藏  举报