與7無關的數-題解
阿新 • • 發佈:2022-03-23
次短路
介紹
次短路其實沒什麼好說的,是一個非常簡單的演算法,和最短路幾乎一樣,但是如果沒有想過那考試的時候還是可能碼錯
具體實現就是在 Dijkstra 基礎上做一些改動,原本的 Dijkstra 是在最短路可以被更新時直接更新,現在加入次短路後就需要分情況討論
如果堆頂資訊比當前節點的次短路還要長就沒有任何貢獻直接扔掉
如果堆頂資訊比當前節點的最短路還要短那麼就把次短路更新為原本的最短路,再把堆頂資訊作為新的最短路並且把節點加入堆
如果堆頂資訊比當前節點的最短路長但是比次短路短,那就把次短路更新為堆頂資訊,由於次短路有可能也能更新後面的節點資訊,所以也需要把這個節點加入堆中
不難發現,由於我們只需要最短路和次短路,所以這個節點第一次從堆中被取出時它的最短路就確定了(就像普通的 Dijkstra 一樣),第二次從堆中被取出時它的次短路也就確定了
Code
#include<bits/stdc++.h> #define in read() using namespace std; #define getchar() (S==T&&(T=(S=B)+fread(B,1,1<<15,stdin),S==T)?EOF:*S++) char B[1<<15],*S=B,*T=B; inline int read() { char c=getchar(); int x=0; while(c<48)c=getchar(); while(c>47)x=(x*10)+(c^48),c=getchar(); return x; } inline void mwrite(int a) { if(a>9)mwrite(a/10); putchar((a%10)|48); } inline void write(int a,char c) { mwrite(a); putchar(c); } #define MAXN 5003 #define MAXM 200005 #define INF 2100000000 int n,m; int dis[MAXN][3];//dis[i][0]表示1到節點i的最短路長度,dis[i][1]表示1到節點i的次短路長度 struct Node { int id,dis; bool operator <(const Node& x)const { return dis>x.dis; } Node(int Id=0,int Dis=0):id(Id),dis(Dis){} }; int head[MAXN],nxt[MAXM],to[MAXM],w[MAXM],cnt; inline void create(int ff,int tt,int ww){nxt[++cnt]=head[ff],head[ff]=cnt,to[cnt]=tt,w[cnt]=ww;} inline void dij() { for(int i=1;i<=n;++i) dis[i][0]=dis[i][1]=INF; dis[1][0]=0; priority_queue<Node> q; q.push((Node){1,0}); int pos,d; while(!q.empty()) { pos=q.top().id,d=q.top().dis,q.pop(); if(d>dis[pos][1]) continue;//如果即將更新的資訊比節點的次短路更大就直接捨棄 for(int i=head[pos];i;i=nxt[i]) { if(dis[to[i]][0]>d+w[i])//如果即將更新的資訊比節點的最短路更小就讓最短路替換次短路,讓新資訊更新最短路 { dis[to[i]][1]=dis[to[i]][0]; q.push((Node){to[i],dis[to[i]][0]=d+w[i]}); } if(dis[to[i]][0]<d+w[i]&&dis[to[i]][1]>d+w[i])//如果即將更新的資訊比節點的最短路大但是比次短路小就讓新資訊更新次短路 q.push((Node){to[i],dis[to[i]][1]=d+w[i]});//即使僅更新了次短路也應該加入優先佇列,因為可能更新其他節點的次短路 } } } signed main() { n=in,m=in; for(int i=1,t1,t2,t3;i<=m;++i) { t1=in,t2=in,t3=in; create(t1,t2,t3); create(t2,t1,t3); } dij(); write(dis[n][1],'\n'); return 0; }
該文為本人原創,轉載請註明出處