【bzoj1726】Roadblocks
1726: [Usaco2006 Nov]Roadblocks第二短路
Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 1578 Solved: 795
[Submit][Status][Discuss]
Description
貝茜把家搬到了一個小農場,但她常常回到FJ的農場去拜訪她的朋友。貝茜很喜歡路邊的風景,不想那麽快地結束她的旅途,於是她每次回農場,都會選擇第二短的路徑,而不象我們所習慣的那樣,選擇最短路。 貝茜所在的鄉村有R(1<=R<=100,000)條雙向道路,每條路都聯結了所有的N(1<=N<=5000)個農場中的某兩個。貝茜居住在農場1,她的朋友們居住在農場N(即貝茜每次旅行的目的地)。 貝茜選擇的第二短的路徑中,可以包含任何一條在最短路中出現的道路,並且,一條路可以重復走多次。當然咯,第二短路的長度必須嚴格大於最短路(可能有多條)的長度,但它的長度必須不大於所有除最短路外的路徑的長度。
Input
* 第1行: 兩個整數,N和R,用空格隔開
* 第2..R+1行: 每行包含三個用空格隔開的整數A、B和D,表示存在一條長度為 D(1 <= D <= 5000)的路連接農場A和農場B
Output
* 第1行: 輸出一個整數,即從農場1到農場N的第二短路的長度
Sample Input
4 41 2 100
2 4 200
2 3 250
3 4 100
Sample Output
450輸出說明:
最短路:1 -> 2 -> 4 (長度為100+200=300)
第二短路:1 -> 2 -> 3 -> 4 (長度為100+250+100=450)
HINT
Source
Gold
題意:
求無向圖中$1\rightarrow N$的嚴格次短路長度。
題解:
樹上次長鏈都會維護了,圖上次短路怎麽能不會……
考慮常用的$Dijkstra$的運行過程,每次從優先隊列隊首挑一個$dis$最小的點,該點的$dis$就被確定下來(都是正權邊一定沒有再能更新他的邊)。
然後通過該點松弛與之相連的其他點並把它們扔到優先隊列中。扔到$N$即可退出。
那麽次短路同理,在優先隊列中出現的第一個不等於該點最短路的次短路一定是唯一確定的(沒有再能更新他的最短路或次短路)。
於是只需要記錄該點最短路和次短路是否出現過,並在往優先隊列裏push的時候標記上這是最短路還是次短路即可。
註意最短路若被更新,次短路要繼承最短路的值。
代碼:(md我優先隊列排序排反還在bzoj上$A$了是什麽操作啊)
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include<queue> using namespace std; #define MAXN 100005 #define MAXM 500005 #define INF 0x7fffffff #define ll long long struct node{ int u,d,c; bool operator<(const node b)const{ return d>b.d; } }; int hd[MAXN],to[MAXM<<1]; int nxt[MAXM<<1],cst[MAXM<<1]; int N,M,cnt,dis[MAXN][2]; bool vis[MAXN][2]; inline int read(){ int x=0,f=1; char c=getchar(); for(;!isdigit(c);c=getchar()) if(c==‘-‘) f=-1; for(;isdigit(c);c=getchar()) x=x*10+c-‘0‘; return x*f; } inline void addedge(int u,int v,int w){ to[++cnt]=v,cst[cnt]=w; nxt[cnt]=hd[u],hd[u]=cnt; return; } inline int Dijkstra(int s){ memset(dis,63,sizeof(dis)); memset(vis,0,sizeof(vis)); priority_queue<node> q; q.push({1,0,0}); dis[1][0]=0; while(!q.empty()){ node h=q.top();q.pop(); if(vis[h.u][h.c]) continue; vis[h.u][h.c]=1; for(int i=hd[h.u];i;i=nxt[i]){ int u=h.u,v=to[i],w=cst[i]; if(dis[v][0]>h.d+w){ dis[v][1]=dis[v][0]; dis[v][0]=h.d+w; q.push(node{v,dis[v][0],0}); q.push(node{v,dis[v][1],1}); } if(dis[v][1]>h.d+w && h.d+w!=dis[v][0]){ dis[v][1]=h.d+w; q.push(node{v,dis[v][1],1}); } } } return dis[N][1]; } int main(){ N=read(),M=read(); for(int i=1;i<=M;i++){ int u=read(),v=read(),w=read(); addedge(u,v,w);addedge(v,u,w); } printf("%d\n",Dijkstra(1)); return 0; }
【bzoj1726】Roadblocks