注意:此次短路可以走重边
点击查看代码
/*
次短路:
边可以重复走
1.以1为起点跑最短路,以n为起点跑最短路。
2.枚举每一条边,次短路只可能是两种情况:
(1)最短路上的最短的一条边跑三次
(2)除了最短路外的其他能到n的次短路
*/
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
const int inf=0x3f3f3f3f;
typedef long long ll;
typedef pair<int,int> pii;
int n,m;
int head[maxn],cnt=0;
struct edge{
int u,v,next;
int w;
}e[maxn<<2];
void add(int u,int v,int w){
e[cnt].u=u;e[cnt].v=v;e[cnt].w=w;e[cnt].next=head[u];head[u]=cnt++;
}
void init(){
memset(head,-1,sizeof(head));cnt=0;
}
int dis1[maxn],dis2[maxn];
bool vis[maxn];
void dij(int s,int d[]){
for (int i=0;i<=n;i++) d[i] = inf;
memset(vis,0,sizeof(vis));
d[s]=0;
priority_queue<pii,vector<pii>,greater<pii> > q;
q.push({d[s],s});
while(!q.empty()){
int u=q.top().second;
q.pop();
if(vis[u]) continue;
vis[u]=1;
for (int i=head[u];~i;i=e[i].next){
int v=e[i].v,w=e[i].w;
if(d[v]>d[u]+w){
d[v]=d[u]+w;
q.push({d[v],v});
}
}
}
}
int main(){
init();
scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
u++;v++;
add(u,v,w);add(v,u,w);
}
dij(1,dis1);dij(n,dis2);
int ans1=dis1[n],ans2=inf;
int mi = inf;
for (int i=0;i<cnt;i++){
int u=e[i].u,v=e[i].v;
int w=e[i].w;
if(dis1[u]+dis2[v]+w > ans1) ans2=min(ans2,dis1[u]+dis2[v]+w);//大于最短路的路径中的最小的
if(dis1[u]+dis2[v]+w == ans1) mi=min(mi,w);//找最短路中的最小的一条边
}
printf("%d\n",min(ans2,ans1+mi*2));
return 0;
}