题目:
描述
贝茜把家搬到了一个小农场,但她常常回到FJ的农场去拜访她的朋友。贝茜很喜欢路边的风景,不想那么快地结束她的旅途,于是她每次回农场,都会选择第二短的路径,而不象我们所习惯的那样,选择最短路。 贝茜所在的乡村有R(1<=R<=100,000)条双向道路,每条路都联结了所有的N(1<=N<=5000)个农场中的某两个。贝茜居住在农场1,她的朋友们居住在农场N(即贝茜每次旅行的目的地)。 贝茜选择的第二短的路径中,可以包含任何一条在最短路中出现的道路,并且,一条路可以重复走多次。当然咯,第二短路的长度必须严格大于最短路(可能有多条)的长度,但它的长度必须不大于所有除最短路外的路径的长度。
输入
- 第1行: 两个整数,N和R,用空格隔开
- 第2…R+1行: 每行包含三个用空格隔开的整数A、B和D,表示存在一条长度为 D(1 <= D <= 5000)的路连接农场A和农场B
输出
- 第1行: 输出一个整数,即从农场1到农场N的第二短路的长度
样例
输入
4 4
1 2 100
2 4 200
2 3 250
3 4 100
输出
450
提示
//最短路:1 -> 2 -> 4 (长度为100+200=300)
第二短路:1 -> 2 -> 3 -> 4 (长度为100+250+100=450)
这道题要求次短路,我们可以选择A*,不会SPFA来暴力做,但是稍有不慎就会超时,每一点时间都不要浪费。
SPFA本来是用来求最短路的,那我们就来变形,把dist改为二维的,第一维存放最短路,第二维放次短路。
如过当前求到的最短路
d
i
s
t
[
v
]
[
0
]
+
e
d
g
e
[
i
]
dist[v][0]+edge[i]
dist[v][0]+edge[i]可以小于以前求到的最短路
d
i
s
t
[
n
o
w
]
[
0
]
dist[now][0]
dist[now][0],那我们就现将现在这个点的次短路也就是以前的最短路更新为次短路的值,再更新最短路的值。
dst[v][1]=dst[v][0];
dst[v][0]=dst[now][0]+eg[i];
如过当前求到的值比以前最短路的值大 d i s t [ v ] [ 0 ] + e d g e [ i ] < d i s t [ n o w ] [ 0 ] dist[v][0]+edge[i]<dist[now][0] dist[v][0]+edge[i]<dist[now][0],但却又比次短路的值小,我们就将其更新为次短路的值 d i s t [ v ] [ 1 ] > d i s t [ n o w ] [ 0 ] + e d g e [ i ] dist[v][1]>dist[now][0]+edge[i] dist[v][1]>dist[now][0]+edge[i],我们就直接将其更新为次短路的值
dst[v][1]=dst[now][0]+eg[i];
如过当前求到的值不大于以前的最短路但却又比以前的次短路大 d i s t [ v ] [ 1 ] > d i s t [ n o w ] [ 1 ] + e d g e [ i ] dist[v][1]>dist[now][1]+edge[i] dist[v][1]>dist[now][1]+edge[i],我们就将以前的次短路直接更新为求到的值.
dst[v][1]=dst[now][1]+eg[i];
还有就是要注意一下这道题用SPFA有点勉强,正解还是A*,因为代码里面会用到memset,所以数组也要卡着开,建议用快读或scanf,不要用cin,我就深受其害
下面是完整代码:
#include <bits/stdc++.h>
using namespace std;
/*上面已经讲了核心判断部分,其余和SPFA差不多,
所以就不注释代码了,起始主要还是我懒,~逃*/
int n,m,vis[5010],dst[5010][2],head[5010],nxt[200010],to[200010],tot,eg[200010];
int read() {
int sum=0,fg=1;
char c=getchar();
while(c<'0'||c>'9') {
if(c=='-')fg=-1;
c=getchar();
}
while(c>='0'&&c<='9') {
sum=sum*10+c-'0';
c=getchar();
}
return sum*fg;
}
void add(int x,int y,int c) {
tot++;
nxt[tot]=head[x];
to[tot]=y;
eg[tot]=c;
head[x]=tot;
}
void spfa(int s) {
memset(dst,0x3f3f3f,sizeof(dst));
dst[s][0]=0;
// dst[1][1]=0;
vis[s]=0;
queue<int>q;
q.push(s);
while(!q.empty()) {
int now=q.front();
q.pop();
vis[now]=0;
for(int i=head[now]; i; i=nxt[i]) {
int v=to[i];
if(dst[v][0]>dst[now][0]+eg[i]) {
dst[v][1]=dst[v][0];
dst[v][0]=dst[now][0]+eg[i];
if(!vis[v]) {
q.push(v);
vis[v]=1;
}
}
if(dst[v][1]>dst[now][0]+eg[i]&&dst[v][0]<dst[now][0]+eg[i]) {
dst[v][1]=dst[now][0]+eg[i];
if(!vis[v]) {
q.push(v);
vis[v]=1;
}
}
if(dst[v][1]>dst[now][1]+eg[i]) {
dst[v][1]=dst[now][1]+eg[i];
if(!vis[v]) {
q.push(v);
vis[v]=1;
}
}
}
}
}
int main() {
n=read();
m=read();
for(int i=1; i<=m; i++) {
int a,b,c;
a=read();
b=read();
c=read();
add(a,b,c);
add(b,a,c);
}
spfa(n);
cout<<dst[1][1];
return 0;
}