5866: 桃子寻宝

4 篇文章 0 订阅
1 篇文章 0 订阅

5866: 桃子寻宝 

Time Limit(Common/Java):3000MS/9000MS     Memory Limit:65536KByte

Description

 

 

桃子最近正在玩一个游戏,游戏有若干个关卡(每个关卡地图相同)组成,每个关卡有且仅有一个宝藏,并需要从入口1进入迷宫,找到宝藏,然后到出口n。

但是由于不知道宝藏的具体位置,桃子经常瞎走,导致浪费很多时间,于是乎,桃子便写了个脚本程序,一下就知道了宝藏的具体位置,但是桃子并不知道怎么走才走最少的路,便找到了聪明的你。

 

 

Input

 

 

第一行为一个整数T(1≤T≤11),代表有T组数据。

对于每组数据,第一行三个整数n,m,q(1≤n≤5*103,0≤m≤105,1≤q≤105),分别代表n个点,m条边,q个关卡。

接下来m行,每行三个整数u,v,c(1≤u,v≤n,1≤c≤109),分别代表u和v(u与v不相同)之间有一条可以双向行走的通道,长度为c。

接下来有q行,每行一个整数p(1≤p≤n),代表宝藏位置。

数据保证任何两个点之间最多只存在一条边。

 

 

Output

 

 

对于每组数据输出q行,每行输出一个整数,为最少需要走多少路才能找到宝藏并到达出口,若拿不到宝藏或拿到宝藏走不到出口则输出-1。

 

 

 

Sample Input

1
4 2 4
1 2 1
2 4 2
1
2
3
4

Sample Output

3
3
-1
3

Source

 

思路:实际上就是求起点到中间节点的最短距离+终点到中间节点的最短距离

那么只要求两次单源最短路径即可

利用spfa算法,spfa算法是Bellman-ford 的队列优化形式

#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
typedef long long ll;
const int MAXN = 1e5+10;
struct edge{
	int to; 
	ll cost;
	edge(){};
	edge(int to,ll cost):to(to),cost(cost){};
};
ll d[2][MAXN];
//edge map[MAXN];

vector<edge> map[MAXN];

const ll INF = 0x3f3f3f3f3f3f3f3f;
int T,N,M,Q;
bool inQue[MAXN];

void spfa(ll *dist,int src){
	//需要注意指针的初始化,
	//如果有指针初始化的话,要注意范围
	//并且初始化方式要如下所示 
//	memset(dist,63,sizeof(int)*(N+1));
	memset(inQue,0,sizeof(inQue));
	queue<int> que;	
	while(!que.empty()) que.pop();
	dist[src] = 0;
	inQue[src] = true;
	que.push(src); 
	
	while(!que.empty()){
		int u = que.front(); que.pop();
		
		for(int i=0;i<map[u].size();i++){
			int v = map[u][i].to;
			ll cost = map[u][i].cost;
			if(dist[u] + cost<dist[v]){
				dist[v] = dist[u] + cost;
				
				if(!inQue[v]){
					inQue[v] = true;
					que.push(v); 
				}
			}
		}
		inQue[u] = false;
	}	
//	for(int i=1;i<=N;i++)
//		printf("%lld ",dist[i]);
//	printf("\n");
}


int main(){
	scanf("%d",&T);
	while(T--){
		scanf("%d%d%d",&N,&M,&Q);
//		memset(d[0],63,sizeof(d[0]));
//		memset(d[1],63,sizeof(d[1]));
		fill(d[0],d[0]+1+N,INF);
		fill(d[1],d[1]+1+N,INF);
		
		for(int i=1;i<=M;i++){
			int a,b;
			ll c;
			scanf("%d%d%lld",&a,&b,&c);
			map[a].push_back(edge(b,c));
			map[b].push_back(edge(a,c));
		}
		
		spfa(d[0],1);
		spfa(d[1],N);
		
		for(int i=1;i<=Q;i++){
			int a;
			scanf("%d",&a);
			if( d[0][a] ==INF ||  d[1][a] ==INF ){
				printf("-1\n"); continue;	
			}
			ll sum = d[0][a] + d[1][a]; 
			printf("%lld\n",sum);
		}
		
		for(int i=0;i<=N;i++){
			map[i].clear();
		}
	}
	return 0;
}

一下几点需要注意一下

1.数组,容器的初始化很重要,不然很坑!!

2.对应的输出类型要注意下,这里 边的长度可以达到10^9 所以两者相加,,int会超,所以要用longlong,细节问题要注意

3.对指针的memset需要人为的计算内存大小。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值