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

P9377 百合 题解

P9377 百合

推销我的洛谷博客。

题意

给定三个整数 \(k,m,s\),现有 \(2^k\) 个点和 \(m\) 条带权边,点的下标从 \(0\) 开始。

同时,还有 \(k\) 个整数 \(a_1\sim a_k\),你可以花费 \(a_t\) 的代价从 \(x\) 走到 \(y\),其中 \(t\)\(x\)\(y\) 在二进制表示下不同的比特数。

问从 \(s\) 开始到每个点的最短路长度。

数据范围

  • \(1\leqslant k\leqslant 17\)
  • \(1\leqslant m\leqslant 2\times 10^5\)
  • \(0\leqslant s\leqslant 2^k\)
  • \(0\leqslant a_i,c\leqslant 2^{30}-1\)

思路

一道比较复杂的最短路问题。

首先能想到把 \(a_i\) 进行差分,然后在 \(2^k\times k\) 个点之间跑最短路……

但有两个问题,没有保证 \(a\) 具有单调性,即差分后可能存在负权边,也就是不能使用 dij,二是有负权边则可能会出现反复横跳的情况,即从 \((x,i)\)\((y,i+1)\) 再到 \((x,i+2)\),这种情况是不合法的,但并不好判断。

于是考虑建更多的点,令 \((x,i,j)\) 表示考虑前 \(i\) 位是否进行反转,一共反转了 \(j\) 位,最终数值为 \(x\)。但如果用差分数组来表示边权的话则仍会有负权边的问题,于是考虑最后再算 \(a\) 的值,具体而言:

  • \((x,i,j)\) 连向 \((x,i+1,j)\),表示第 \(i\) 位不进行反转,边权为 \(0\)
  • \((x,i,j)\) 连向 \((x\oplus 2^i,i+1,j+1)\),表示第 \(i\) 位进行反转,边权为 \(0\)
  • \((x,i,j)\) 连向 \(x\),表示结算瞬移操作,边权为 \(a_j\)

这样就能够避免反复横跳和负权边的问题,对这张图跑 dij,复杂度 \(O((2^kk^2+m)\log 2^kk^2)\),难以通过。

注意到 \((x,i,j)\) 部分有大量权为 \(0\) 的边,无需优先队列,所以考虑用 bfs 特殊处理这一部分,这样就可以把复杂度优化至 \(O(2^kk^2+(2^kk+m)\log 2^kk)\)

同时由于空间紧张,bfs 部分需要开 bool 数组。

复杂度

  • 时间:\(O(2^kk^2+(2^kk+m)\log 2^kk)\)
  • 空间:\(O(2^kk^2+m)\)

Code

点击查看代码
#include <iostream>
#include <vector>
#include <queue>
#include <tuple>
#define _1 (__int128)1using namespace std;
using ll = long long;
using pii = pair<int, int>;
using tp = tuple<int, int, int>;void FileIO (const string s) {freopen((s + ".in").c_str(), "r", stdin);freopen((s + ".out").c_str(), "w", stdout);
}const int T = (1 << 17) + 5;int p, m, st, dis[T], mx, a[20];
bool vis[T][20][20];
vector<pii> g[T];
priority_queue<pii, vector<pii>, greater<pii>> pq;
queue<tp> q;void Record (int x, int lv) {if (lv > mx + 10 || (dis[x] && lv >= dis[x])) return ;pq.push({lv, x}), dis[x] = lv;
}void Record_ (int x, int y, int z) {if (vis[x][y][z]) return ;vis[x][y][z] = 1, q.push({x, y, z});
}void bfs (int x, int lv) {Record_(x, 0, 0);while (q.size()) {auto [y, i, j] = q.front();q.pop(), Record(y, lv + a[j]);if (i < p) Record_(y, i + 1, j), Record_(y ^ (1 << i), i + 1, j + 1);}
}void dij () {Record(st, 1);while (pq.size()) {auto [lv, x] = pq.top();pq.pop();if (dis[x] != lv) continue;bfs(x, lv);for (auto [i, j] : g[x])Record(i, lv + j);}
}signed main () {ios::sync_with_stdio(0), cin.tie(0);// FileIO("");cin >> p >> m >> st;for (int i = 1; i <= p; i++)cin >> a[i], mx = max(mx, a[i]);for (int i = 1, x, y, z; i <= m; i++)cin >> x >> y >> z, g[x].push_back({y, z}), g[y].push_back({x, z});dij();for (int i = 0; i < (1 << p); i++) cout << dis[i] - 1 << ' ';return 0;
}
http://www.jsqmd.com/news/1358531/

相关文章:

  • 深度解析WandEnhancer:开源游戏修改器增强方案的完整技术实现
  • Java原子类原理与应用:高并发编程核心技术解析
  • 向量数据库与FAISS索引:RAG系统高效检索的核心原理与实战选型指南
  • 2026年张家港铝型材切割机定制加工行业靠谱服务商介绍:工业切铝机厂家选择指南 - 海棠依旧大
  • BetterNCM插件管理器完整安装指南:5分钟解决网易云音乐插件难题
  • 2026 无锡卫生间防水靠谱、经验丰富、信誉好的公司推荐:专业卫生间防水,安居无忧(8 月防水最新资讯) - 超人防水
  • Java Web酒店管理系统开发实战与架构设计
  • 中国著名有影响力的定制调查研究咨询公司
  • 技术眩晕感:从AI辅助编码到自动化工作流的范式跃迁应对指南
  • 英伟达布局AI基站背后:计算与通信融合的技术逻辑与开发者机遇
  • 索引+Explain搞定慢查询全流程
  • 魔兽争霸3终极辅助工具:5分钟解决现代电脑兼容性问题
  • TongWeb7类加载冲突问题解析与解决方案
  • Robot Framework自动化测试入门:从环境搭建到实战应用
  • 配电网韧性提升:MPS预配置与动态调度优化实践
  • 2026年“华数杯”国际大学生数学建模竞赛 ICM 问题B:谁将赢得全球人工智能竞赛?B 题方案一:熵权 TOPSIS + 灰色预测 GM(1,1) + 线性规划 —— 思路
  • 如何免费解锁AMD Ryzen处理器的隐藏性能:SMUDebugTool终极指南
  • 《人类简史》中的虚构故事与人类文明演进
  • 昌吉同城漏水检测上门服务,家庭建筑防水修缮避坑科普(2026 新版) - 昵19226106854
  • Linux命名管道原理与应用实战
  • 2026年十堰装修最全选购指南!工艺、付款、工期全解析 - 国麟测评
  • 衡阳市建设学校网站:如何真正赋能教育数字化,助力师生成长
  • Mac彻底卸载OpenClaw全攻略:清理Docker容器、镜像与系统残留
  • Docker容器技术原理【第四课】
  • tkinter Text组件Selection事件机制解析与实践
  • Codex定时运行:从Crontab到企业级自动化任务编排与管理平台
  • AI智能体交互革命:从复杂配置到“按住说话”的自然融合
  • 如何彻底解决Windows系统卡顿问题?3步轻松清理C盘让电脑飞起来
  • 2026年国内减压阀市场选购指南:产业格局、评估框架与主流品牌对比 - 上海泵阀科技网
  • Unity运行时撤销重做系统实现:从命令模式到状态快照的完整方案