算法思想
记d[v]为节点1到v的最短路,d_[v]为次短路,对于一条u->v的边,d_[v]要么是d_[u]加边权要么是d[u]加边权。即
设若1->v只有一条路,d_[v]=INF。
和Dijkstra算法类似,每次先判断经过u的这条路径是否可以更新最短路,如果不能更新,就看能否更新次短路,如果可以更新,就用之前的最短路更新次短路。由于每次都要用到节点u的次短路的信息,所以每次都要push节点的次短路。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#define rep(i,st,ed) for(int i=st;i<=ed;++i)
using namespace std;
const int N=5001,M=1E5+1,INF=0x3f3f3f3f;
int n,r,tot;
int d[N],d_[N],head[N],vis[N];
struct Node{
int p,dis;
bool operator < (const Node &tmp) const
{
return dis>tmp.dis;
}
};
struct Edge{
int to,val,nxt;
}e[2*M];
priority_queue<Node> q;
inline void add_edge(int u,int v,int w,int flag)
{
e[++tot].nxt=head[u];e[tot].to=v;e[tot].val=w;head[u]=tot;
if(flag)
add_edge(v,u,w,0);
}
inline int read()
{
int ret=0;char ch=getchar();
while(ch<'0' || ch>'9')
ch=getchar();
while(ch>='0' && ch<='9')
{
ret=ret*10+ch-'0';
ch=getchar();
}
return ret;
}
void S_Dijkstra()
{
rep(i,1,n)
{
d[i]=INF;
d_[i]=INF;
}
d[1]=0;
Node fir={1,0};
q.push(fir);
while(!q.empty())
{
Node cur=q.top();q.pop();
int u=cur.p;
for(int i=head[u];i;i=e[i].nxt)
{
int v=e[i].to,dis=cur.dis+e[i].val;
if(d_[v]<dis)
continue;
if(d[v]>dis)
{
swap(dis,d[v]);
Node tmp={v,d[v]};
q.push(tmp);
}
if(d_[v]>dis && d[v]<dis)
{
d_[v]=dis;
Node tmp={v,d_[v]};
q.push(tmp);
}
}
}
}
int main()
{
// freopen("in.in","r",stdin);
n=read();r=read();
int u,v,w;
rep(i,1,r)
{
u=read();v=read();w=read();
add_edge(u,v,w,1);
}
S_Dijkstra();
cout<<d_[n]<<endl;