当前位置:首页 > 技术 > 正文内容

带费用限制的最短路径SPFA+优先队列

访客 技术 2026年8月10日 3

poj1724

ROADS

时间限制: 1000MS | 内存限制: 65536K

总提交数: 10751 | 已通过: 3952

描述

有N个编号为1到N的城市,它们之间由单向道路连接。每条道路有两个参数:长度和过路费(以硬币数量表示)。 Bob和Alice原本住在城市1。由于发现Alice在他们常玩的纸牌游戏中作弊,Bob与她分手并决定搬到城市N。他希望尽快到达那里,但手头资金有限。

我们需要帮助Bob找到从城市1到城市N的一条路径,使得总费用不超过他拥有的硬币数K,并且路径总长度最短。

输入格式

  • 第一行包含整数K(0 ≤ K ≤ 10000),表示Bob最多可以支付的硬币数。
  • 第二行包含整数N(2 ≤ N ≤ 100),表示城市的总数。
  • 第三行包含整数R(1 ≤ R ≤ 10000),表示道路总数。
  • 接下来R行中,每行四个整数S、D、L、T,分别表示:
    • S:起点城市(1 ≤ S ≤ N)
    • D:终点城市(1 ≤ D ≤ N)
    • L:道路长度(1 ≤ L ≤ 100)
    • T:过路费(0 ≤ T ≤ 100)

输出格式

输出一行,包含一个整数,表示在费用不超过K的前提下,从城市1到城市N的最短路径长度。如果不存在这样的路径,则输出-1。

样例输入

5
6
7
1 2 2 3
2 4 3 3
3 4 2 4
1 3 4 1
4 6 2 1
3 5 2 0
5 4 3 2

样例输出

11

题意说明

本题看似是典型的双约束最短路问题,即先使费用最小,再在费用最小的前提下使距离最短。然而这种思路存在缺陷:即使当前已知最小费用cost < K,其所对应的最短路径可能不是全局最优解。可能存在另一种情况,花费为cost1(cost < cost1 ≤ K),而其对应的最短路径比之前的更优。

因此,采用优先队列优化的SPFA算法来解决此问题。每当访问某节点时,若当前累计费用不超过K,则将该节点加入队列。同一节点可能多次入队和出队,优先队列确保在费用不超过K的前提下,优先处理距离最小的节点,从而避免上述问题。

实现代码

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;

const int MAXN = 110;
const int MAXM = 10010;

struct Edge {
    int to, len, cost;
    int next;
} edges[MAXM * 2];

int head[MAXN], edgeCount;
int maxCost, numCities, numEdges;

void initGraph() {
    edgeCount = 0;
    memset(head, -1, sizeof(head));
}

void addEdge(int from, int to, int length, int cost) {
    edges[edgeCount].to = to;
    edges[edgeCount].len = length;
    edges[edgeCount].cost = cost;
    edges[edgeCount].next = head[from];
    head[from] = edgeCount++;
}

struct State {
    int city, distance, cost;
    
    bool operator>(const State& other) const {
        if (distance == other.distance)
            return cost > other.cost;
        return distance > other.distance;
    }
};

int spfa(int start, int end) {
    priority_queue<State, vector<State>, greater<State>> pq;
    State initial = {start, 0, 0};
    pq.push(initial);
    
    while (!pq.empty()) {
        State current = pq.top();
        pq.pop();
        
        if (current.city == end)
            return current.distance;
            
        for (int i = head[current.city]; i != -1; i = edges[i].next) {
            State next = {
                edges[i].to,
                current.distance + edges[i].len,
                current.cost + edges[i].cost
            };
            
            if (next.cost <= maxCost) {
                pq.push(next);
            }
        }
    }
    
    return -1;
}

int main() {
    while (scanf("%d", &maxCost) != EOF) {
        scanf("%d%d", &numCities, &numEdges);
        initGraph();
        
        for (int i = 0; i < numEdges; ++i) {
            int from, to, len, cost;
            scanf("%d%d%d%d", &from, &to, &len, &cost);
            addEdge(from, to, len, cost);
        }
        
        int result = spfa(1, numCities);
        printf("%d\n", result);
    }
    return 0;
}

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。