目录:
题目:
分析:
从起始点跑到终点,单元最短路,所以我们就很容易联想到
SPFA
S
P
F
A
,正常应该是跑两遍
SPFA
S
P
F
A
,一次算出起点到终点,另一次终点到起点,但小编偏偏就要用一遍
SPFA
S
P
F
A
但怎么做呢,我们可以在原来的
SPFA
S
P
F
A
的基础上进行修改,把原来的队列q,改为
q[i][0..1]
q
[
i
]
[
0..1
]
,
q[i][0]
q
[
i
]
[
0
]
代表父节点,
q[i][1]
q
[
i
]
[
1
]
代表最近一次更改后的距离
把原来的最短路
dis
d
i
s
,改为
dis[i][0..1]
d
i
s
[
i
]
[
0..1
]
,分别为起点到点i的最短路和次短路
最后输出
dis[终点][1]
d
i
s
[
终
点
]
[
1
]
代码:
#pragma GCC optimize("Os")
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define LL long long
using namespace std;
inline LL read() {
LL d=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
return d*f;
}
int ls[200001];
struct edg{
int to,next,w;
}t[200001];
int cnt=0;
void add(int x,int y,int w)
{
t[cnt]=(edg){y,ls[x],w};
ls[x]=cnt++;
}
int main()
{
/* freopen("block.in","r",stdin);
freopen("block.out","w",stdout);*/
int n=read(),m=read();
memset(ls,-1,sizeof(ls));
for(int i=1;i<=m;i++)
{
int a=read(),b=read(),w=read();
add(a,b,w);add(b,a,w);
}
int dis[5001][2],q[100001][2];
for(int i=1;i<=5000;i++)
dis[i][0]=dis[i][1]=99999999;
q[1][0]=1;q[1][1]=0;dis[1][0]=0;
int head=0,tail=1;
while(head<=tail)
{
head++;
int u=q[head][0],d=q[head][1];
for(int i=ls[u];~i;i=t[i].next)
{
int v=t[i].to,w=d+t[i].w;
if(w<dis[v][0])
{
swap(dis[v][0],w);
q[++tail][0]=v;q[tail][1]=dis[v][0];
}
if(w>dis[v][0]&&w<dis[v][1])
{
dis[v][1]=w;
q[++tail][0]=v;q[tail][1]=dis[v][1];
}
}
}
printf("%d",dis[n][1]);
fclose(stdin);
fclose(stdout);
return 0;
}