5866: 桃子寻宝Time Limit(Common/Java):3000MS/9000MS Memory Limit:65536KByteDescription
桃子最近正在玩一个游戏,游戏有若干个关卡(每个关卡地图相同)组成,每个关卡有且仅有一个宝藏,并需要从入口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 Sample Output 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需要人为的计算内存大小。