当前位置: 首页 > backend >正文

恰好边数限制的最短路(边的数量很大)

题目

345. 牛站

算法标签: B e l l m a n − F o r d Bellman-Ford BellmanFord算法, 倍增算法, 矩阵乘法

思路

注意到, 最短路有边数限制, 直接考虑 B e l l m a n − F o r d Bellman-Ford BellmanFord算法, 但是这里求得是恰好 k k k条边的最短路, 因此每次更新的时候都需要重置转移数组, 并且这样的时间复杂度是 O ( n m ) O(nm) O(nm)的有可能会超时, 因此需要进行优化, 可以预处理一个状态转移数组 f [ i ] [ j ] [ k ] f[i][j][k] f[i][j][k]表示从点 i i i j j j经过了 2 k 2 ^ k 2k步的最短路, 这样只需要像快速幂一样将二进制数中的每个 1 1 1取出就能得到答案

B e l l m a n − F o r d Bellman-Ford BellmanFord代码

#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>using namespace std;const int N = 210, M = N * N;int n, m, s, t;
struct Edge {int u, v, w;
} edges[M];
int d[N], tmp[N];
vector<int> desc;int get(int val) {return lower_bound(desc.begin(), desc.end(), val) - desc.begin();
}void bellman_ford() {memset(d, 0x3f, sizeof d);d[s] = 0;for (int i = 0; i < n; ++i) {memcpy(tmp, d, sizeof d);memset(d, 0x3f, sizeof d);for (int k = 0; k < m; ++k) {auto &[u, v, w] = edges[k];if (tmp[u] + w < d[v]) d[v] = tmp[u] + w;if (tmp[v] + w < d[u]) d[u] = tmp[v] + w;}}
}int main() {ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);cin >> n >> m >> s >> t;for (int i = 0; i < m; ++i) {int u, v, w;cin >> u >> v >> w;edges[i] = {u, v, w};desc.push_back(u), desc.push_back(v);}sort(desc.begin(), desc.end());desc.erase(unique(desc.begin(), desc.end()), desc.begin());//将点进行离散化s = get(s), t = get(t);for (int i = 0; i < m; ++i) {auto &[u, v, w] = edges[i];u = get(u), v = get(v);}bellman_ford();cout << d[t] << "\n";return 0;
}

倍增算法代码

算法瓶颈在预处理, 时间复杂度 O ( n 3 ) O(n ^ 3) O(n3)

#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>using namespace std;const int N = 210, M = N * N, K = 21;int n, m, s, t;
struct Edge {int u, v, w;
} edges[M];
vector<int> desc;
int f[N][N][K];int get(int val) {return lower_bound(desc.begin(), desc.end(), val) - desc.begin();
}int main() {ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);cin >> n >> m >> s >> t;for (int i = 0; i < m; ++i) {int u, v, w;cin >> u >> v >> w;edges[i] = {u, v, w};desc.push_back(u), desc.push_back(v);}sort(desc.begin(), desc.end());desc.erase(unique(desc.begin(), desc.end()), desc.begin());//将点进行离散化s = get(s), t = get(t);for (int i = 0; i < m; ++i) {auto &[u, v, w] = edges[i];u = get(u), v = get(v);}memset(f, 0x3f, sizeof f);for (int k = 0; k < K; ++k) {for (int i = 0; i < desc.size(); ++i) {for (int j = 0; j < desc.size(); ++j) {for (int l = 0; l < desc.size(); ++l) {f[i][j][k] = min(f[i][j][k], f[i][l][k - 1] + f[l][j][k - 1]);}}}}int ans[N], tmp[N];ans[s] = 0;for (int k = 0; k < K; ++k) {if (n >> k & 1) {memset(tmp, 0x3f, sizeof tmp);for (int i = 0; i < desc.size(); ++i) {for (int j = 0; j < desc.size(); ++j) {tmp[i] = min(tmp[i], ans[j] + f[j][i][k]);}}memcpy(ans, tmp, sizeof tmp);}}cout << ans[t] << "\n";return 0;
}
http://www.xdnf.cn/news/2766.html

相关文章:

  • 《淘宝 API 数据湖构建:实时商品详情入湖 + Apache Kafka 流式处理指南》
  • MySQL最新版9.3.0安装教程
  • PyCharm 2023升级2024 版本
  • Linux:ftp 配置实验
  • terraform使用workspace管理多工作环境
  • List--链表
  • 【C++ 核心知识点面试攻略:从基础到实战(上位机开发视角)】
  • Linux调试器 - gdb使用指南
  • 【虚幻5蓝图Editor Utility Widget:创建高效模型材质自动匹配和资产管理工具,从3DMax到Unreal和Unity引擎_系列第二篇】
  • Rabbitmq下载和安装(Windows系统,百度网盘)
  • SQL Server 存储过程开发规范
  • 普通IT的股票交易成长史--20250428晚
  • InferType和_checked_type的区别?
  • 开发vue项目所需要安装的依赖包
  • leetcode128-最长连续序列
  • 聊天室系统:多任务版TCP服务端程序开发详细代码解释
  • Qt C++数据库实验
  • FPGA-数字时钟
  • whois为什么有时会返回两个不同的域名状态
  • 【Linux】Java 开发者的 Linux 常用命令指南
  • 2024ICPC成都题解
  • Golang实现函数默认参数
  • 人工智能数学基础(一):人工智能与数学
  • 动态规划问题 -- 斐波那契数列模型(解码方法)
  • etcd 的安装及使用
  • 软件评测师考点重点知识
  • ubuntu安装docker,conda,tmux,btop,nvitop
  • 一种用于从视网膜图像中识别疾病的 BERT 式自监督学习 CNN
  • 大模型训练平台:重构 AI 研发范式的智慧基建
  • MCU内存映射技术详解