Roadblocks 次短路径
- Description
贝西所在的牧场一共有 N 个地点。M 条双向通行的道路连接这些地点,其中第i条道路连接 Ai 和 Bi ,长度为 Li 。贝西想从第一个地点走到第 N 个地点,由于路上风景不错,她决定不走最短路径,而选择次短路径。次短路径的长度严格大于最短路径。如果有两条路径的长度都是最短的,那么它们都不算次短路径。次短路径允许重复通过一些道路或地点。请你帮助贝西找出次短路径的长度吧,输入数据保证次短路径一定存在。
- Input Format
第一行:两个整数 N 和 M ,1 ≤ N ≤ 5000 , 1 ≤ M ≤ 10^5
第二行到第 M+1 行:第 i+1 行有三个整数 Ai ,Bi 和 Li ,1 ≤Ai ,Bi ≤ N , 1 ≤ Li ≤5000
- Output Format
单个整数:表示从第一个点到最后一个点的次短路径长度
- Sample Input
4 4
1 2 100
2 4 200
2 3 250
3 4 100
- Sample Output
450
- Hint
最短路是 1 → 2 → 4,总长度为300,次短路是 1 → 2 → 3 → 4,总长度为 450
- 分析
一题Spfa裸体,无非就是多记录一下每到个点的次短路,然后松弛的时候分别用次短路和最短路更新。要注意的是题意说次短路严格大于最短路,所以在更新次短路是要判断是否等于最短路。
#include <queue>
#include <stack>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
queue <int> Q;
int n,m,u,v,w,tot,In[5005],Dist[5005][2],last[5005];
struct Data{int to,next,val;}E[200005];
void Addline(int u,int v,int w){
E[++tot].to=v; E[tot].next=last[u]; last[u]=tot; E[tot].val=w;
E[++tot].to=u; E[tot].next=last[v]; last[v]=tot; E[tot].val=w;
}
int main(){
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++){
scanf("%d%d%d",&u,&v,&w);
Addline(u,v,w);
}
memset(Dist,127/2,sizeof(Dist));
for (Q.push(1),Dist[1][0]=0;!Q.empty();){
u=Q.front(); In[u]=0; Q.pop();
for (int i=last[u];i;i=E[i].next){
v=E[i].to;
if (Dist[u][1]+E[i].val<Dist[v][1] && Dist[u][1]+E[i].val!=Dist[v][0]){
Dist[v][1]=Dist[u][1]+E[i].val;
if (!In[v]) Q.push(v),In[v]=1;
}
if (Dist[v][1]<Dist[v][0]) swap(Dist[v][0],Dist[v][1]);
if (Dist[u][0]+E[i].val<Dist[v][1] && Dist[u][0]+E[i].val!=Dist[v][0]){
Dist[v][1]=Dist[u][0]+E[i].val;
if (!In[v]) Q.push(v),In[v]=1;
}
if (Dist[v][1]<Dist[v][0]) swap(Dist[v][0],Dist[v][1]);
}
}
printf("%d",Dist[n][1]);
fclose(stdin); fclose(stdout);
return 0;
}