Hdu4725 The Shortest Path in Nya Graph(最短路,建图)

题意:

有n个点,m条边,每经过路i需要wi元。并且每一个点都有自己所在的层。一个点都乡里的层需要花费c元,问从1到N最小花费?

思路:

主要是建图。
把楼层单独抽象出来作为节点。
N个点,然后有N层,每个楼层用两个点,一个入,一个出,所以要抽象2N个点。
总共是3
N个点。

点1——N就是对应的实际的点1~N. 要求的就是1到N的最短路。

然后点N+1 ~ 3*N 是N层楼层抽象出来的点。

第i层,入边到N+2i-1, 出边从N+2i 出来。(1<= i <= N)

N + 2i - 1 到 N + 2(i+1) 加边长度为C. 表示从第i层到第i+1层。

N + 2*(i+1) - 1 到 N + 2*i 加边长度为C, 表示第i+1层到第i层。

如果点i属于第u层,那么加边 i ——> N + 2u -1 , N + 2u ——> i 长度都为0

跑最短路

#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long LL;
const int INF = 0x3f3f3f3f;
const int maxn = 1000010;
using namespace std;
int n,m,lc;

int head[maxn], cur;
struct Edge{
	int v,w,next;
};
Edge edges[maxn];
void init(){
	for(int i = 0; i < maxn; ++i) head[i] = -1;
	cur = 0;
}
void addEdge(int u, int v, int w){
	edges[cur].v = v; edges[cur].w = w;
	edges[cur].next = head[u]; head[u] = cur++;
}

struct Node{
	int u,d;
	Node(int a, int b):u(a),d(b){}
	bool operator < (const Node& rhs) const{
		return d > rhs.d;
	}
};
int d[maxn];
bool vis[maxn];
int Dijkstra(int s, int t){
	for(int i = 1; i < maxn; ++i) { d[i] = INF; vis[i] = 0; }
	d[s] = 0;
	priority_queue<Node> Q;
	Q.push(Node(s, 0));
	while(!Q.empty()){
		Node t = Q.top(); Q.pop();
		int u = t.u;
		if(vis[u]) continue;
		vis[u] = 1;
		for(int i = head[u]; i != -1; i = edges[i].next){
			int v = edges[i].v, w = edges[i].w;
			if(d[v] > d[u] + w){
				d[v] = d[u] + w;
				Q.push(Node(v, d[v]));
			}
		}
	}
	if(d[t] == INF) return -1;
	return d[t];
}

int main()
{
    freopen("in.txt","r",stdin);
    int T; scanf("%d",&T);
    int kase = 1;
	while(T--){
		scanf("%d%d%d",&n,&m,&lc); init();
		for(int i = 1; i <= n; ++i){
			int x; scanf("%d",&x);
			addEdge(i, n+2*x-1, 0); 
			addEdge(n+2*x, i, 0);
		}
		// 楼层之间 
		for(int i = 1; i < n; ++i){
			addEdge(n+2*i-1, n+2*(i+1), lc);
			addEdge(n+2*(i+1)-1, n+2*i, lc);
		}
		for(int i = 0; i < m; ++i){
			int a,b,c; scanf("%d%d%d", &a,&b,&c);
			addEdge(a, b, c); 
			addEdge(b, a, c);
		}
		
		printf("Case #%d: %d\n", kase++, Dijkstra(1, n));
	}
    fclose(stdin);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值