【USACO】2006 Nov Roadblocks 次短路径

本文介绍了一种解决次短路径问题的方法,使用SPFA算法并记录每个节点的次短路径,确保次短路径严格大于最短路径。通过具体实例说明了如何实现这一算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值