HDU 4725 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
题意:T组数据,每组第一行有三个数N,M,C,代表有N层,M条边的关系;
第二行是N数,代表每个点所在层数。
接下来M行,每行是三个数,u,v,w,表示u到v的权值是w,双向边。
求1到N的最短路径。如果存在就输出结果,不存在就输出-1.
 
把层也当成结点,所以层到层中的结点为0, 层到层的花费为C,
结点u到结点v之间的花费为w,为了方便起见,将层设为N+i结点
所以数组要开大一点,是原来的两倍。 
不知道为什么用栈写会超时, 用队列也很快就过了。
 
具体请看代码。 
#include <queue>
#include <stack>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
#define inf 0x3f3f3f3f
const int maxn = 100005;
int lay[2*maxn];
int dis[2*maxn];
int book[2*maxn];
int head[2*maxn];
struct node{
	int e, w;
	int next;
	void Node(int x, int y, int z) {
		e = x; w = y; next = z;
	}
}e[40*maxn];
void init(int n, int m) {
	memset(lay, 0, sizeof(lay));
	memset(book, 0, sizeof(book));
	memset(dis, inf, sizeof(dis));
	memset(head, -1, sizeof(head));
}
void SPFA_sta() {//会超时 
	memset(book, 0, sizeof(book));
	dis[1] = 0;
	int pre, nex;
	stack<int> sta;
	sta.push(1);
	while(!sta.empty()) {
		pre = sta.top();
		sta.pop();
		book[pre] = 0;
		for(int i = head[pre]; i != -1; i = e[i].next) {
			nex = e[i].e;
			if(dis[nex] > dis[pre] + e[i].w) {
				dis[nex] = dis[pre] + e[i].w;
				if(!book[nex]) {
					book[nex] = 1;
					sta.push(nex);
				}
			}
		}
	}
}
void SPFA_que() {//358ms 
	memset(book, 0, sizeof(book));
	dis[1] = 0;
	int pre, nex;
	queue<int> q;
	q.push(1);
	while(!q.empty()) {
		pre = q.front();
		q.pop();
		book[pre] = 0;
		for(int i = head[pre]; i != -1; i = e[i].next) {
			nex = e[i].e;
			if(dis[nex] > dis[pre] + e[i].w) {
				dis[nex] = dis[pre] + e[i].w;
				if(!book[nex]) {
					book[nex] = 1;
					q.push(nex);
				}
			}
		}
	}
}
int main() {
	int T;
	int li, t;
	int N, M, C;
	int u, v, w;
	int Case = 1;
	scanf("%d", &T);
	while(T--) {
		t = 0;
		scanf("%d %d %d", &N, &M, &C);
		init(N, M);
		for(int i = 1; i <= N; i++) {
			scanf("%d", &li);
			lay[i] = li;
			book[li] = 1;
		}
		for(int i = 1; i < N; i++) {
			if(book[i] && book[i+1]) {//层与层建边 
				e[t].Node(N+i, C, head[i+N+1]);//将层当成结点建边 
				head[i+N+1] = t;
				t++;
				e[t].Node(N+i+1, C, head[N+i]);
				head[i+N] = t;
				t++;
			}
		}
		for(int i = 1; i <= N; i++) {//层与点建边
			e[t].Node(i, 0, head[lay[i]+N]);
			head[lay[i]+N] = t;
			t++;
			if(lay[i] > 1) {
				e[t].Node(lay[i]-1+N, C, head[i]);//与上一层建边 
				head[i] = t;
				t++;
			}
			if(lay[i] < N){
				e[t].Node(lay[i]+1+N, C, head[i]);//与下一层建边 
				head[i] = t;
				t++;
			}
		}
		for(int i = 1; i <= M; i++) {//点与点建边 
			scanf("%d %d %d", &u, &v, &w);//双向边 
			e[t].Node(v, w, head[u]);
			head[u] = t;
			t++;
			e[t].Node(u, w, head[v]);
			head[v] = t;
			t++;
		}
		SPFA_que();
		//SPFA_sta();
		if(dis[N] != inf)
		printf("Case #%d: %d\n", Case++, dis[N]);
		else printf("Case #%d: -1\n", Case++);
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值