ACM学习历程—HDU4725 The Shortest Path in Nya Graph(SPFA && 优先队列)
Description
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
题目大意是是有n层。然后每层会有部分点,点与点可以通过特点的代价互达,相邻层之间的点可以通过C代价到达。
题目一开始没有看到每层可以有多个点。还有需要注意的是同层之间的点不能直接0代价到达。
之前在没考虑同层间不能直接0代价互达的时候,是把每个层看作一个节点,这样某层的节点到这个节点的代价都是0。
如果考虑到这个条件的话,
所以需要构造出下面这样的路径:
为每层设置From和To节点。某层的节点只能从From节点前往,或者前往To节点。
而相邻层之间亦是如此。
这样就能避免同层代价为0这个问题了。
为了避免点的冲突,From从n开始往后,To从2n开始往后。
需要注意的是这样操作以后点的数目上界会变成3N,线段就是6N。
这里采用链式前向星存图,采用STL优先队列的SPFA。
代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #include <utility> #include <queue> #include <vector> #define N 300005 using namespace std; typedef pair<int, int> pii; struct Edge { int to; int next; int val; }edge[2*N]; int head[N], cnt; void addEdge(int u, int v, int w) { edge[cnt].to = v; edge[cnt].next = head[u]; edge[cnt].val = w; head[u] = cnt; cnt++; } int dis[N]; bool vis[N]; int n, m, c; inline int idFrom(int i) { return i + n; } inline int idTo(int i) { return i + 2*n; } void Input() { memset(head, -1, sizeof(head)); memset(dis, -1, sizeof(dis)); memset(vis, 0, sizeof(vis)); dis[1] = 0; cnt = 0; int k, v, w; scanf("%d%d%d", &n, &m, &c); for (int i = 1; i <= n; ++i) { scanf("%d", &k); addEdge(idFrom(k), i, 0); addEdge(i, idTo(k), 0); } for (int i = 1; i < n; ++i) { addEdge(idTo(i), idFrom(i+1), c); addEdge(idTo(i+1), idFrom(i), c); } for (int i = 0; i < m; ++i) { scanf("%d%d%d", &k, &v, &w); addEdge(k, v, w); addEdge(v, k, w); } } void Work() { pii k; priority_queue <pii, vector<pii>, greater<pii> > q; q.push(pii(0, 1)); while (!q.empty()) { k = q.top(); q.pop(); int x = k.second; if (vis[x]) continue; vis[x] = true; for (int i = head[x]; i != -1; i = edge[i].next) { if (dis[edge[i].to] != -1 && dis[edge[i].to] <= dis[x] + edge[i].val) continue; if (vis[edge[i].to]) continue; dis[edge[i].to] = dis[x] + edge[i].val; q.push(pii(dis[edge[i].to], edge[i].to)); } } printf("%d\n", dis[n]); } int main() { //freopen("test.in", "r", stdin); int T; scanf("%d", &T); for (int times = 1; times <= T; ++times) { printf("Case #%d: ", times); Input(); Work(); } return 0; }
把每一道题当作难题去做。
posted on 2015-05-26 21:33 AndyQsmart 阅读(201) 评论(0) 编辑 收藏 举报