HDU4725 The Shortest Path in Nya Graph 最短路分层

一、内容

 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;
} 
发布了414 篇原创文章 · 获赞 380 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/qq_41280600/article/details/104208728