一、内容
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.
Input
The 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.
Output
For 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
二、思路
- 由于每层很很多点, 它们可以通过c互相到达,如果 每层22点之间都建一条边的话,n2 条边肯定是不行的。 那么可以考虑新建一个层级点作为中间节点。
- 通过这样建图就可以把n2的边减少为 5N 的边 。 再加上额外的2N条边, 那么总共是 7N条边。所以开存边的话7N大就行了。 由于多了层级点,那么点数变成2N。
三、代码
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
const int N = 2e5 + 5, M = 7e5 + 5, INF = 0x3f3f3f3f;
struct E {
int v, w, next;
} e[M];
struct Node {
int v, d; //le代表第几层
Node(int d, int v):d(d), v(v) {}
bool operator < (const Node&w) const {
return d > w.d;
}
};
int t, n, m, c, u, v, w, len, h[N], d[N];
bool vis[N];
void add(int u, int v, int w) {
e[len].v = v;
e[len].w = w;
e[len].next = h[u];
h[u] = len++;
}
int djkstra() {
memset(d, 0x3f, sizeof(d));
memset(vis, false, sizeof(vis));
d[1] = 0;
priority_queue<Node> q;
q.push(Node(0, 1));
while (!q.empty()) {
int u = q.top().v;
q.pop();
if (vis[u]) continue;
vis[u] = true;
if (u == n) return d[n];
//可以更新上层 和 下层
for (int j = h[u]; j; j = e[j].next) {
int v = e[j].v;
int w = e[j].w + d[u];
if (d[v] > w) {
d[v] = w;
q.push(Node(d[v], v));
}
}
}
if (d[n] == INF) return -1;
return d[n];
}
int main() {
scanf("%d", &t);
for (int cas = 1; cas <= t; cas++) {
memset(h, 0, sizeof(h)); len = 1;
scanf("%d%d%d", &n, &m, &c);
for (int i = 1; i <= n; i++) {
scanf("%d", &u);
//层级点(n + 层级)到本层的点 边权为0 单向
add(n + u, i, 0);
//本层的点到 上下2层级点 边权为c 双向
add(i, n + u + 1, c), add(n + u + 1, i, c);
if (u != 1) add(i, n + u - 1, c), add(n + u - 1, i, c);
}
for (int i = 1; i <= m; i++) {
scanf("%d%d%d", &u, &v, &w);
add(u, v, w); add(v, u, w);
}
printf("Case #%d: %d\n", cas, djkstra());
}
return 0;
}