题目链接:路障
思路
- 次短路,顾名思义就是比当前最短路小的”最短路“,因此还是需要求出最短路
- 显而易见,次短路便是基于最短路的一种拓展
- 现在来分析一下次短路应具有的特点
- 小于最短路(以此得出当Dis[u]+E[i].dis==Dis[v]时,不能进行次短路更新,否则会导致次短路等于最短路)
- 大于其他路(因此,次短路只可能是从最短路Dis[u]或次短路Ans[u],到达v的)
- 如果有新最短路,则原最短路为新次短路
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
const int Max_N=5010,Max_M=1e5+7,inf=2147432637;
typedef pair<int,int>node;
struct Edge
{
int next,dis,to;
} E[Max_M*2];//注意是无向图
int Head[Max_N],num_Edge,Dis[Max_N],vis[Max_N],Ans[Max_N];
int N,M;
inline int Read(void)//快读
{
int w=0,x=0;
char ch=0;
while(!isdigit(ch)) w|=ch=='-',ch=getchar();
while(isdigit(ch)) x=x*10+(ch^48),ch=getchar();
return w?-x:x;
}
inline void Add_Edge(int from,int to,int dis)//建边
{
E[++num_Edge].dis=dis;
E[num_Edge].next =Head[from];
E[num_Edge].to =to;
Head[from]=num_Edge;
}
inline void Dijkstra()
{
queue<int>Q;
for(int i=1; i<=N; ++i) Dis[i]=inf,Ans[i]=inf;//初始化,注意也要对次短路进行初始化
Dis[1]=0;
Q.push(1) ;
while(!Q.empty())
{
int u=Q.front();
Q.pop() ;
vis[u]=0;
for(int i=Head[u]; i; i=E[i].next )
{
int v=E[i].to;
if(Dis[v]>Dis[u]+E[i].dis )//如果找到新的最短路
{
Ans[v]=Dis[v];//更新次小最短路
Dis[v]=Dis[u]+E[i].dis ;
if(!vis[v])
{
vis[v]=1;
Q.push(v) ;
}
}
else if(Ans[v]>Dis[u]+E[i].dis&&Dis[u]+E[i].dis!=Dis[v])//如果当前路径比最短路大,且小于次短路,则更新次短路
{
Ans[v]=Dis[u]+E[i].dis ;//如果当前路径比次小最短路短,则更新次小最短路
if(!vis[v])
{
vis[v]=1;
Q.push(v) ;
}
}
if(Ans[v]>Ans[u]+E[i].dis)//如果当前路径比次小最短路短,则更新次小最短路
{
Ans[v]=Ans[u]+E[i].dis ;//如果当前路径比次小最短路短,则更新次小最短路
if(!vis[v])
{
vis[v]=1;
Q.push(v) ;
}
}
}
}
}
int main(void)
{
N=Read(),M=Read();
for(int i=1; i<=M; ++i)
{
int u=Read(),v=Read(),d=Read();
Add_Edge(u,v,d);
Add_Edge(v,u,d);
}
Dijkstra();
printf("%d",Ans[N]);
return 0;
}