一、内容
虽然草儿是个路痴(就是在杭电待了一年多,居然还会在校园里迷路的人,汗~),但是草儿仍然很喜欢旅行,因为在旅途中 会遇见很多人(白马王子,^0^),很多事,还能丰富自己的阅历,还可以看美丽的风景……草儿想去很多地方,她想要去东京铁塔看夜景,去威尼斯看电影,去阳明山上看海芋,去纽约纯粹看雪景,去巴黎喝咖啡写信,去北京探望孟姜女……眼看寒假就快到了,这么一大段时间,可不能浪费啊,一定要给自己好好的放个假,可是也不能荒废了训练啊,所以草儿决定在要在最短的时间去一个自己想去的地方!因为草儿的家在一个小镇上,没有火车经过,所以她只能去邻近的城市坐火车(好可怜啊~)。
Input
输入数据有多组,每组的第一行是三个整数T,S和D,表示有T条路,和草儿家相邻的城市的有S个,草儿想去的地方有D个;
接着有T行,每行有三个整数a,b,time,表示a,b城市之间的车程是time小时;(1=<(a,b)<=1000;a,b 之间可能有多条路)
接着的第T+1行有S个数,表示和草儿家相连的城市;
接着的第T+2行有D个数,表示草儿想去地方。
Output
输出草儿能去某个喜欢的城市的最短时间。
Sample Input
6 2 3
1 3 5
1 4 7
2 8 12
3 8 4
4 9 12
9 10 2
1 2
8 9 10
Sample Output
9
二、思路
- 由于起点有很多个,需要求出这些点到不同点的最短路。每次对某个起点进行一次djkstra效率太低。故我们考虑建立一个0点,0点和多个起点都建立一条边,权值为0。
- 这样就转化为0点到其他点的最短路问题了, 就只需要一次djkstra即可。
三、代码
#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
using namespace std;
const int N = 2005, INF = 0x3f3f3f3f;
struct E {
int v, w, next;
} e[N * 100];
struct Node {
int v, d;
Node(int v, int d):v(v), d(d) {}
bool operator < (const Node &w)const {
return d > w.d;
}
};
int m, S, D, len, head[N], d[N];
bool vis[N];
void add(int u, int v, int w) {
e[len].v = v;
e[len].next = head[u];
e[len].w = w;
head[u] = len++;
}
void djkstra() {
int u;
memset(d, 0x3f, sizeof(d));
memset(vis, false, sizeof(vis));
priority_queue<Node> q;
q.push(Node(0, 0));
d[0] = 0;
while (!q.empty()) {
u = q.top().v;
q.pop();
if (vis[u]) continue;
vis[u] = true;
for (int j = head[u]; j != -1; j = e[j].next) {
int v = e[j].v;
int w = e[j].w;
if (!vis[v] && d[v] > d[u] + w) {
d[v] = d[u] + w;
q.push(Node(v, d[v]));
}
}
}
}
int main() {
while (scanf("%d%d%d", &m, &S, &D) != EOF) {
len = 0;
memset(head, -1, sizeof(head));
int u, v, w;
for (int i = 1; i <= m; i++) {
scanf("%d%d%d", &u, &v, &w);
add(u, v, w);
add(v, u, w);
}
//将小草附近的点都加入队列作为起点
for (int i = 1; i <= S; i++) {
scanf("%d", &v);
add(0, v, 0);
add(v, 0, 0);
}
djkstra();
int ans = 0x7f7f7f7f;
for (int i = 1; i <= D; i++) {
scanf("%d", &v);
ans = min(ans, d[v]);
}
printf("%d\n", ans);
}
return 0;
}