题目描述
有一天,琪琪想乘坐公交车去拜访她的一位朋友。
由于琪琪非常容易晕车,所以她想尽快到达朋友家。
现在给定你一张城市交通路线图,上面包含城市的公交站台以及公交线路的具体分布。
已知城市中共包含 n 个车站(编号1~n)以及 m 条公交线路。
每条公交线路都是 单向的,从一个车站出发直接到达另一个车站,两个车站之间可能存在多条公交线路。
琪琪的朋友住在 s 号车站附近。
琪琪可以在任何车站选择换乘其它公共汽车。
请找出琪琪到达她的朋友家(附近的公交车站)需要花费的最少时间。
样例
输入
5 8 5
1 2 2
1 5 3
1 3 4
2 4 7
2 5 6
2 3 5
3 5 1
4 5 1
2
2 3
4 3 4
1 2 3
1 3 4
2 3 2
1
1
输出
1
-1
最短路
多个起点,不需要做多遍最短路,只需要构造一个超级源点,使其到其他起点的花费都是0,以这点为起点做一遍最短路即可,图论中一种很常见的小技巧,
或者不加边,如果用spfa做的话,可以直接将所有起点放到队列中。
如果加边了,注意N和M的范围要多开一些。
C++ 代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
//本题考查图论的一个小技巧,超级源点
const int N = 2010, M = 30010,inf = 0x3f3f3f3f;
int h[N],e[M],ne[M],w[M],idx;
int n,m,W,s;
int dist[N];
bool st[N];
void add(int a,int b,int c){
e[idx] = b,w[idx] = c,ne[idx] = h[a],h[a] = idx++;
}
int spfa(){
memset(dist,0x3f,sizeof dist);
dist[0] = 0;
queue<int> q;
q.push(0);
st[0] = true;
while(q.size()){
int t = q.front();
q.pop();
st[t] = false;
for(int i = h[t];~i; i = ne[i]){
int j = e[i];
if(dist[j] > dist[t] + w[i]){
dist[j] = dist[t] + w[i];
if(!st[j]){
st[j] = true;
q.push(j);
}
}
}
}
if(dist[s] == inf) return inf;
return dist[s];
}
int main()
{
while(cin>>n>>m>>s){
memset(h,-1,sizeof h);
idx = 0;
for(int i = 0; i<m; i++){
int a,b,t;
cin>>a>>b>>t;
add(a,b,t);
}
cin>>W;
//构造一个超级源点c,使其到qiqi家附近车站的花费为0
for(int i = 0; i<W; i++){
int k;
cin>>k;
add(0,k,0);
}
if(spfa()!=inf){
cout<<dist[s]<<endl;
}else cout<<-1<<endl;
}
return 0;
}