感受此題可做爲嚴格次短路的模板,所以來寫一寫ios
給定 \(n\) 個點,\(r\) 條雙向道路,求從 \(1\) 號點到 \(n\) 號點的嚴格次短路spa
維護兩個變量,最短路和次短路code
\(Dis[i][0]\) 表示從 \(1\) 號點到 \(i\) 號點的最短路,\(Dis[i][1]\) 表示從 \(1\) 號點到 \(i\) 號點的次短路ip
而後考慮什麼狀況下會對最短路或次短路的更新形成影響get
設 \(fr\) 是當前節點,\(to\) 是當前節點連出去的某個節點string
當 \(Dis[to][0]>Dis[fr][0]+e[i].dis\) 時,代表當前點 \(to\) 的最短路再也不是最短的,就把當前最短路更新成次短路,而後再更新最短路it
當 \(Dis[to][1]>Dis[fr][1]+e[i].dis\) 時,發現當前點 \(to\) 的次短路能夠更短,但對最短路無影響,就只更新次短路io
當 \(Dis[to][1]>Dis[fr][0]+e[i].dis\) 而且 \(Dis[to][0]<Dis[fr][0]+e[i].dis\) 時,代表當前點 \(to\) 的次短路能夠更新,而最短路已是最優,則只更新次短路模板
綜上,每次按上述方法更新每條邊,就能夠求出到每一個點的嚴格次短路class
最後答案就是 \(Dis[n][1]\)
#include<queue> #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #define maxn 5010 #define LL long long #define uLL unsigned long long using namespace std; queue<int> q; int n,r,tot,head[maxn]; int Dis[maxn][3],vis[maxn]; struct edge{int fr,to,dis,nxt;}e[maxn<<1]; inline int read(){ int s=0,w=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();} while(ch>='0'&&ch<='9') s=(s<<1)+(s<<3)+ch-'0',ch=getchar(); return s*w; } inline void add(int fr,int to,int dis){ e[++tot].fr=fr;e[tot].to=to; e[tot].dis=dis;e[tot].nxt=head[fr]; head[fr]=tot; } inline void SPFA(){ while(!q.empty()){ int u=q.front();q.pop(); for(int i=head[u];i;i=e[i].nxt){ int to=e[i].to,dis=e[i].dis; if(Dis[to][0]>Dis[u][0]+dis){ Dis[to][1]=Dis[to][0]; Dis[to][0]=Dis[u][0]+dis; if(!vis[to]) vis[to]=1,q.push(to); } if(Dis[to][1]>Dis[u][1]+dis){ Dis[to][1]=Dis[u][1]+dis; if(!vis[to]) vis[to]=1,q.push(to); } if(Dis[to][1]>Dis[u][0]+dis&&Dis[to][0]<Dis[u][0]+dis){ Dis[to][1]=Dis[u][0]+dis; if(!vis[to]) vis[to]=1,q.push(to); } } } } int main(){ n=read();r=read(); memset(Dis,63,sizeof Dis); q.push(1);vis[1]=1;Dis[1][0]=0; for(int i=1,fr,to,dis;i<=r;i++){ fr=read();to=read();dis=read(); add(fr,to,dis);add(to,fr,dis); } SPFA();printf("%d",Dis[n][1]); return 0; }