HDU

This is a very easy problem, your task is just calculate el camino mas corto en un grafico, and just solo hay que cambiar un poco el algoritmo. If you do not understand a word of this paragraph, just move on.
The Nya graph is an undirected graph with "layers". Each node in the graph belongs to a layer, there are N nodes in total.
You can move from any node in layer x to any node in layer x + 1, with cost C, since the roads are bi-directional, moving from layer x + 1 to layer x is also allowed with the same cost.
Besides, there are M extra edges, each connecting a pair of node u and v, with cost w.
Help us calculate the shortest path from node 1 to node N.

InputThe first line has a number T (T <= 20) , indicating the number of test cases.
For each test case, first line has three numbers N, M (0 <= N, M <= 10 5) and C(1 <= C <= 10 3), which is the number of nodes, the number of extra edges and cost of moving between adjacent layers.
The second line has N numbers l i (1 <= l i <= N), which is the layer of i th node belong to.
Then come N lines each with 3 numbers, u, v (1 <= u, v < =N, u <> v) and w (1 <= w <= 10 4), which means there is an extra edge, connecting a pair of node u and v, with cost w.OutputFor test case X, output "Case #X: " first, then output the minimum cost moving from node 1 to node N.
If there are no solutions, output -1.Sample Input
2
3 3 3
1 3 2
1 2 1
2 3 1
1 3 3

3 3 3
1 3 2
1 2 2
2 3 2
1 3 4
Sample Output
Case #1: 2
Case #2: 3

这题的难点是层数的处理,有两种处理方法。
一种是仔细想可以想到的,用vector把每层的点存下来,在djkstra松弛操作的同时,对当前点的相邻两层点全部松弛一遍(具体看代码)。
第二种应该是正解,就是拆点。其实上一种也相当于拆点,只不过拆很暴力,不够彻底。
我们可以把层当做一个新的点,在该层的点到该层的距离为0,该层到相邻层的距离为c。但因为同层的点不一定相互联通,所以要把一个层分为两个点,一个入口点,一个出口点,入口点和出口点之间不联通。
法一ac代码:
  1 #include <cstdio>
  2 #include <cstring>
  3 #include <iostream>
  4 #include <algorithm>
  5 #include <cmath>
  6 #include <queue>
  7 using namespace std;
  8 typedef long long ll;
  9 const int inf = 0x3f3f3f3f;
 10 const int maxn = 1e5 + 10;
 11 int n, m, c;
 12 int pos[maxn];
 13 vector<int> laye[maxn];
 14 int head[maxn];
 15 int d[maxn];
 16 bool vis[maxn];
 17 bool visi[maxn];
 18 struct edge{
 19     int to, nex, cost;
 20 }eg[2 * maxn];
 21 int cnt = 0;
 22 inline void add(int u,int v,int cost) {
 23     eg[cnt].to = v;
 24     eg[cnt].nex = head[u];
 25     eg[cnt].cost = cost;
 26     head[u] = cnt++;
 27 }
 28 struct Rule {
 29     bool operator () (int &a,int &b) const {
 30         return d[a] > d[b];
 31     }
 32 };
 33 inline void dijkstra(int s) {
 34     memset(vis, 0, sizeof(vis));
 35     memset(d, inf, sizeof(d));
 36     priority_queue<int, vector<int>, Rule> q;
 37     d[s] = 0;
 38     q.push(s);
 39     while(!q.empty()) {
 40         int u = q.top(); q.pop();
 41         for(int k = head[u]; ~k; k = eg[k].nex) {
 42             int v = eg[k].to;
 43             if(d[v] > d[u] + eg[k].cost) {
 44                 //    printf("%d %d %d
", u, v,eg[k].cost);
 45                 d[v] = d[u] + eg[k].cost;
 46                 q.push(v);
 47             }
 48         }
 49         if(pos[u] < n && !vis[pos[u]+ 1]) {
 50             vis[pos[u] +  1] = true;        //注意标记层数,不然会超时
 51             for(int i = 0; i < laye[pos[u] + 1].size(); ++i) {
 52                 int v = laye[pos[u] + 1][i];
 53                 if(d[v] > d[u] + c) {
 54                     //               printf("%d %d %d
", u, v,c);
 55                     d[v] = d[u] + c;
 56                     q.push(v);
 57                     
 58                 }
 59             }
 60         }
 61         if(pos[u]  > 1 && !vis[pos[u] - 1]) {
 62             vis[pos[u] -  1] = true;
 63             for(int i = 0; i < laye[pos[u] - 1].size(); ++i) {
 64                 int v = laye[pos[u] - 1][i];
 65                 if(d[v] > d[u] + c) {
 66                     //             printf("%d %d %d
", u, v,c);
 67                     d[v] = d[u] + c;
 68                     q.push(v);
 69                     
 70                 }
 71             }
 72         }
 73     }
 74 }
 75 int main()
 76 {
 77     int t;
 78     scanf("%d", &t);
 79     for(int cas = 1; cas <= t; ++cas) {
 80         cnt = 0;
 81         memset(head, -1, sizeof(head));
 82         memset(pos, 0, sizeof(pos));
 83         
 84         scanf("%d %d %d", &n, &m, &c);
 85         int u, v, cost;
 86         for(int i = 1; i <= n; ++i) {
 87             scanf("%d", &u);
 88             pos[i] = u;
 89             laye[u].push_back(i);
 90         }
 91         for(int i =0; i < m; ++i) {
 92             scanf("%d %d %d", &u, &v, &cost);
 93             add(u, v, cost);
 94             add(v, u, cost);
 95         }
 96         
 97         dijkstra(1);
 98         if(d[n] == inf || n == 0)
 99             printf("Case #%d: -1
", cas);
100         else
101             printf("Case #%d: %d
", cas, d[n]);
102         for(int i = 1; i <= n; ++i) laye[i].clear();
103     }
104     return 0;
105 }
View Code

法二代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 #include <cmath>
 6 #include <queue>
 7 using namespace std;
 8 typedef long long ll;
 9 const int inf = 0x3f3f3f3f;
10 const int maxn = 5 * 1e5;
11 int n, m, c;
12 int pos[maxn];
13 vector<int> laye[maxn];
14 int head[maxn];
15 int d[maxn];
16 bool vis[maxn];
17 struct edge{
18     int to, nex, cost;
19 }eg[maxn];
20 int cnt = 0;
21 void add(int u,int v,int cost) {
22     eg[cnt].to = v;
23     eg[cnt].nex = head[u];
24     eg[cnt].cost = cost;
25     head[u] = cnt++;
26 }
27 struct Rule {
28     bool operator () (int a,int b) const {
29         return d[a] > d[b];
30     }
31 };
32 void dijkstra(int s) {
33     memset(d, inf, sizeof(d));
34     priority_queue<int, vector<int>, Rule> q;
35     d[s] = 0;
36     q.push(s);
37     while(!q.empty()) {
38         int u = q.top(); q.pop();
39         for(int k = head[u]; k != -1; k = eg[k].nex) {
40             int v = eg[k].to;
41             if(d[v] > d[u] + eg[k].cost) {
42                 //   printf("%d %d %d
", u, v,eg[k].cost);
43                 d[v] = d[u] + eg[k].cost;
44                 q.push(v);
45             }
46             
47         }
48     }
49 }
50 int main()
51 {
52     int t;
53     scanf("%d", &t);
54     for(int cas = 1; cas <= t; ++cas) {
55         
56         cnt = 0;
57         memset(d, inf, sizeof(d));
58         memset(head, -1, sizeof(head));
59         memset(pos, 0, sizeof(pos));
60         scanf("%d %d %d", &n, &m, &c);
61         int u, v, cost;
62         for(int i = 1; i <= n; ++i) {
63             scanf("%d", &u);
64             pos[i] = u;
65             add(i, n + 2 * u - 1, 0);//层内的点到该层距离为0
66             add(n + 2 * u, i, 0);
67             vis[u] = true;
68         }
69         for(int i = 1; i < n; ++i) {
70             if(vis[i] && vis[i + 1]) {//这个似乎不加也行
71                 add(n + 2 * i - 1, n + 2 * (i + 1), c);//相邻层之间的距离为c
72                 add(n + 2 * (i + 1) - 1, n + 2 * i, c);
73             }
74         }
75         for(int i =0; i < m; ++i) {
76             scanf("%d %d %d", &u, &v, &cost);
77             add(u, v, cost);
78             add(v, u, cost);
79         }
80         
81         dijkstra(1);
82         if(d[n] == inf || n == 0)
83             printf("Case #%d: -1
", cas);
84         else
85             printf("Case #%d: %d
", cas, d[n]);
86     }
87     return 0;
88 }
View Code
原文地址:https://www.cnblogs.com/zmin/p/8806633.html