原题见洛谷:题目
分析
直接用一个dis表示最短路,dis2表示次短路。更新有以下几种:
1,dis[j]>dis[i]+w(i,j),直接更新dis[j]并把j入队。
2,dis2[j]>dis[i]+w(i,j),更新dis2[j]并把j入队。注意:此题要求严格小于最短路,所以还需要dis[j]>dis[i]+w(i,j)成立。
3,dis2[j]>dis2[i]+w(i,j),更新dis2[j]并把j入队。
以上三种只取一种。
注意这里的Dij不需要done数组,因为done只是标记最短路更新,但次短路可能还会更新。
#include<bits/stdc++.h>
using namespace std;
const int MAXN=5005;
const int MAXM=100005;
const int INF=400000000;
int N,M,np=0,last[MAXN],dis[MAXN],dis2[MAXN];
struct edge{int to,w,pre;}E[MAXM*2];
struct data
{
int id,d;
friend bool operator < (data a,data b) {a.d>b.d;}
};
char c;
void scan(int &x)
{
for(c=getchar();c<'0'||c>'9';c=getchar());
for(x=0;c>='0'&&c<='9';c=getchar()) x=x*10+c-'0';
}
void addedge(int u,int v,int w)
{
E[++np]=(edge){v,w,last[u]};
last[u]=np;
}
void dij()
{
priority_queue<data>pq;
for(int i=1;i<=N;i++) dis[i]=dis2[i]=INF;
dis[1]=0; pq.push((data){1,0});
while(!pq.empty())
{
data t=pq.top(); pq.pop(); int i=t.id;
for(int p=last[i];p;p=E[p].pre)
{
int j=E[p].to,w=E[p].w;
if(dis[j]>dis[i]+w)
{
dis[j]=dis[i]+w;
pq.push((data){j,dis[j]});
}
else if(dis[j]<dis[i]+w&&dis2[j]>dis[i]+w)
{
dis2[j]=dis[i]+w;
pq.push((data){j,dis[j]});
}
else if(dis2[j]>dis2[i]+w)
{
dis2[j]=dis2[i]+w;
pq.push((data){j,dis[j]});
}
}
}
}
int main()
{
int i,u,v,w;
scan(N);scan(M);
for(i=1;i<=M;i++)
{
scan(u);scan(v);scan(w);
addedge(u,v,w);
addedge(v,u,w);
} dij(); cout<<dis2[N]; return 0;
}