[模板] 次短路 | bzoj1726-[Usaco2006Nov]Roadblocks第二短路
简介
所谓次短路, 顾名思义, 就是第二短路. 😛
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\) 为最短路, \(i - j\) 为一条边.
显然,
\[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;
}