学习心得 - 算法 - 次短路
算一个 ABC 比较常用的工具吧。
(严格)方法 \(1\) Astar + Dij
额这个就是用的 \(k\) 短路改的,\(k=2\)。
这个不用代码。
(严格)方法 \(2\) Dij 维护信息
就是在 Dij 的时候多维护一个次短路然后更新即可。
#include<bits/stdc++.h>
using namespace std;
const int N=5e3+10;
vector<pair<int,int>>e[N];
int n,r,dis[N][2];
struct dij{
int p,d;
};
bool operator<(dij x,dij y){
return x.d>y.d;
}
bool vis[N];
priority_queue<dij>q;
signed main(){
cin>>n>>r;
for(int i=1;i<=r;i++){
int u,v,w;
cin>>u>>v>>w;
e[u].push_back({v,w});
e[v].push_back({u,w});
}
memset(dis,0x3f,sizeof(dis));
dis[1][0]=0;
q.push({1,0});
while(q.size()){
auto f=q.top();
q.pop();
vis[f.p]=1;
for(auto v:e[f.p]){
if(f.d+v.second<dis[v.first][0]){
dis[v.first][1]=dis[v.first][0];
dis[v.first][0]=f.d+v.second;
q.push({v.first,dis[v.first][0]});
}
if(f.d+v.second<dis[v.first][1]
&&f.d+v.second>dis[v.first][0]){
dis[v.first][1]=f.d+v.second;
q.push({v.first,dis[v.first][1]});
}
}
}
cout<<dis[n][1];
return 0;
}
(非严格)方法 \(3\) 替换边
从起点 \(s\) 与 \(t\) 各搜一次,然后枚举一条不在原最短路径上的边做替换。
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
vector<array<int,3>>e[N];
int n,m,dis[N][2],fir;
pair<int,int>pre[N];
vector<array<int,3>>g;
struct dij{
int p,d;
};
bool operator<(dij x,dij y){
return x.d>y.d;
}
bool vis[3*N];
priority_queue<dij>q;
void rep(){
int p=n;
while(p){
vis[pre[p].second]=1;
p=pre[p].first;
}
return;
}
signed main(){
cin>>n>>m;
for(int i=1;i<=m;i++){
int u,v,w;
cin>>u>>v>>w;
e[u].push_back({v,w,i});
g.push_back({u,v,w});
e[v].push_back({u,w,i});
}
memset(dis,0x3f,sizeof(dis));
dis[1][0]=0;
q.push({1,0});
while(q.size()){
auto f=q.top();
q.pop();
for(auto v:e[f.p])if(f.d+v[1]<dis[v[0]][0]){
dis[v[0]][0]=f.d+v[1];
pre[v[0]]={f.p,v[2]};
q.push({v[0],dis[v[0]][0]});
}
}
if(dis[n][0]==dis[0][0])
return cout<<-1,0;
dis[n][1]=0;
q.push({n,0});
while(q.size()){
auto f=q.top();
q.pop();
for(auto v:e[f.p])if(f.d+v[1]<dis[v[0]][1]){
dis[v[0]][1]=f.d+v[1];
q.push({v[0],dis[v[0]][1]});
}
}
rep();
int ans=dis[0][0];
for(int i=1;i<=m;i++)if(!vis[i]){
int u=g[i-1][0],v=g[i-1][1],w=g[i-1][2];
ans=min(ans,dis[u][0]+w+dis[v][1]);
ans=min(ans,dis[v][0]+w+dis[u][1]);
}
if(ans==dis[0][0])
return cout<<-1,0;
cout<<dis[n][0]+ans;
return 0;
}
文章同步载入于洛谷,详见文章下方链接。
本文来自博客园,作者:Ivan422,转载请注明原文链接:https://www.cnblogs.com/Exfish/p/23269947。

浙公网安备 33010602011771号