Description
虎是中国传统文化中一个独特的意象。我们既会把老虎的形象用到喜庆的节日装饰画上,也可能把它视作一种邪恶的可怕的动物,例如“武松打虎”或者“三人成虎”。“不入虎穴焉得虎子”是一个对虎的威猛的形象的极好体现,而小强确偏偏进入了虎穴,但问题是怎么出来。
有一个复杂的虎穴包括了N个节点(编号为0至N-1)和M条无向的通道,其中通道i(0<=i<M)连接两个节点R[i][0]和R[i][1],长为L[i]。有K个出口节点,分别为P[0], P[1]至P[K-1]。小强从0号节点出发,他想尽快到达一个出口节点。而洞穴中有一只会瞬间移动的老虎。小强每次到达一个节点,老虎就会瞬间移动到与这个节点相邻的某个通道里使得小强无法使用这个通道。不过,小强一旦选择了另一个没有被封锁的通道,老虎就不会在小强到达这个通道的目的地前改变位置。
老虎非常聪明,它总能让小强离开洞穴所要消耗的时间最长。而小强也非常聪明,他能够计算出最快的逃生方案。
为了让题目更加严谨,我们规定小强的逃生方案是如下的形式:对于每个节点X,给它的所有相邻的边<X,Y>指定一个权值f(X,Y),注意,f(X,Y)不等于f(Y,X);在一个节点,小强选择未被封锁的权值最大的通道逃生,直到到达出口。所有的f(X,Y)两两不同。
你要计算小强的最快逃离时间T并输出。
第一行三个整数 N M K
接下来M行 每行三个整数 表示一条无向边的两端和长度(无重边)
接下来K个整数 表示出口洞穴
Output
小强最快逃离时间T
13 12 9
0 1 1
0 2 4
0 3 11
1 4 11
1 5 7
1 6 15
2 7 3
2 8 13
2 9 23
3 10 3
3 11 1
3 12 2
4 5 6 7 8 9 10 11 12
Sample Output
13
Solution
oyqy神犇SPFA例题。。。维护最短路和次短路。注意因为老虎足够的厉害,因此我们用u的最短路更新v是行不通的,必须用u的次短路更新v的最短路和次短路。
注意图中如果出口在一条链上的话,因为人不可能往回走,因此链上的点没有次短路的。于是我们不更新它。这个记录一下v是由哪个点更新的就能避免。
为何蒟蒻的常数永远这么大QAQ。。。

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
| #include <cstdio>
#include <algorithm>
#include <queue>
using namespace std;
typedef long long LL;
const int INF = 1009999999;
int getint() {
int r = 0, k = 1; char c = getchar();
for (; '0' > c || c > '9'; c = getchar()) if (c == '-') k = -1;
for (; '0' <= c && c <= '9'; c = getchar()) r = r * 10 - '0' + c;
return r * k;
}
struct edge_type {
int to, next, w;
} edge[2000005];
int cnte = 1, h[100005];
void ins(int x, int y, int z) {
edge[++cnte].to = y;
edge[cnte].next = h[x];
edge[cnte].w = z;
h[x] = cnte;
}
int n, m, k;
queue<int> Q;
int din[100005], dis[100005], pre[100005];
bool vis[100005];
void SPFA() {
for (int i = 1; i <= n; ++i) din[i] = dis[i] = INF;
int now;
for (int i = 1; i <= k; ++i) {
now = getint() + 1;
dis[now] = din[now] = 0;
Q.push(now);
vis[now] = true;
}
while (!Q.empty()) {
now = Q.front(); Q.pop();
vis[now] = false;
for (int i = h[now]; i; i = edge[i].next) {
int v = edge[i].to;
if (dis[v] >= din[now] + edge[i].w) {
if (pre[v] != now)
din[v] = dis[v];
dis[v] = din[now] + edge[i].w;
pre[v] = now;
if (!vis[v]) {
vis[v] = true;
Q.push(v);
}
} else {
if (din[v] > din[now] + edge[i].w) {
din[v] = din[now] + edge[i].w;
if (!vis[v]) {
vis[v] = true;
Q.push(v);
}
}
}
}
}
}
int main() {
n = getint(); m = getint(); k = getint();
int x, y, z;
for (int i = 0; i < m; ++i) {
x = getint() + 1; y = getint() + 1; z = getint();
ins(x, y, z);
ins(y, x, z);
}
SPFA();
printf("%d", din[1]);
return 0;
}
|