[模板] 次短路 | bzoj1726-[Usaco2006Nov]Roadblocks第二短路
阿新 • • 發佈:2018-11-01
簡介
所謂次短路, 顧名思義, 就是第二短路. :P
1到n的次短路長度必然產生於:1到x的最短路 + edge(x,y) + y到n的最短路
簡單證明一下:
設 \(dis(i,j)\) 表示 \(i\) 到 \(j\) 的最短路.
假設次短路有兩條不在最短路圖上的邊, 即路徑
\[d1: 1 - i - j - k - l - n\]
其中 \(1 - i\), \(j - k\), \(l - n\) 為最短路, \(i - j\), \(k - l\) 為兩條邊.
我們可以構造出路徑
\[ d2: 1 - i - j - n \]
其中 \(1 - i\), \(j - n\)
顯然,
\[dis(j,n) < dis(j,k) + e(k,l) + dis(l,n)\]
也就是說, \(d2\) 長度小於 \(d1\);
\[dis(1,n) < dis(1,i) + e(i,j) + dis(j,n)\]
也就是說, \(d2\) 長度大於 \(1\) 到 \(n\) 的最短路.
因此, \(d1\) 不是次短路, 矛盾.
有更多條不在最短路圖上的邊時同理.
QED.
所以, 用 dij 求一下 \(1\) 點到各點的最短路和 \(n\) 點到各點的最短路, 列舉邊即可.
程式碼見下.
bzoj1726-[Usaco2006Nov]Roadblocks第二短路
板子題.
#include<cstdio> #include<iostream> #include<cmath> #include<cstring> #include<algorithm> #include<queue> #include<set> #include<map> using namespace std; #define rep(i,l,r) for(register int i=(l);i<=(r);++i) #define repdo(i,l,r) for(register int i=(l);i>=(r);--i) #define il inline typedef double db; typedef long long ll; //-------------------------------------- const int nsz=5050,msz=1e5+50,ninf=1e9+50; int n,m; struct te{int t,v,pr;}edge[msz*2]; int hd[nsz],pe=1; void adde(int f,int t,int v){edge[++pe]=(te){t,v,hd[f]};hd[f]=pe;} void adddb(int f,int t,int v){adde(f,t,v);adde(t,f,v);} int dis1[nsz],dis2[nsz]; int vi[nsz]; struct tnd{int t,d;}; bool operator<(tnd l,tnd r){return l.d>r.d;} void dij(int f,int *dis){ priority_queue<tnd> pq; rep(i,1,n)dis[i]=ninf,vi[i]=0; dis[f]=0; pq.push((tnd){f,0}); int u,v,cnt=0; while(!pq.empty()){ u=pq.top().t;pq.pop(); if(vi[u])continue; vi[u]=1; for(int i=hd[u];i;i=edge[i].pr){ v=edge[i].t; if(dis[v]>dis[u]+edge[i].v){ dis[v]=dis[u]+edge[i].v; pq.push((tnd){v,dis[v]}); } } ++cnt; if(cnt==n)break; } rep(i,1,n)cout<<dis[i]<<' '; cout<<'\n'; } int sol(){ int ans=ninf,tmp; dij(1,dis1); dij(n,dis2); rep(i,2,pe){ tmp=dis1[edge[i^1].t]+edge[i].v+dis2[edge[i].t]; if(tmp>dis1[n]&&tmp<ans)ans=tmp; } return ans; } int main(){ ios::sync_with_stdio(0),cin.tie(0); cin>>n>>m; int a,b,c; rep(i,1,m){ cin>>a>>b>>c; adddb(a,b,c); } cout<<sol()<<'\n'; return 0; }