堆优化Dijkstra算法详解:从稀疏图挑战到洛谷P4779模板实战
1. 项目概述从一道题到一套方法论如果你正在准备算法竞赛或者在学习数据结构与算法的路上那么“单源最短路径”绝对是一个绕不开的经典问题。而洛谷上的P4779这道题被冠以“【模板】”之名其地位不言而喻——它几乎是所有选手在掌握基础Dijkstra算法后必须跨越的第一道性能门槛。这道题的核心远不止是让你写出一个能算出最短路径的程序它真正的价值在于逼迫你思考如何将理论算法O(n²)的朴素Dijkstra进行工程化、高效化的改造以应对大规模稀疏图的挑战。简单来说它要求你实现一个“堆优化的Dijkstra算法”。为什么“堆优化”如此关键想象一下你有一张城市地图城市节点多达10^5个道路边也可能达到10^5条这就是典型的稀疏图。朴素的Dijkstra每次都要遍历所有节点来寻找当前距离起点最近的那个这就像在一个人山人海的广场上每次都用大喇叭喊“谁离我最近”然后所有人都在回应你再去一一比对。这个操作的时间复杂度是O(n²)在数据量上去之后必然超时。堆优化的核心思想就是给这个广场上的每个人发一个智能手环这个手环能实时报告自己的距离而你手里有一个控制台能瞬间找到距离最小的那个人。这个“智能手环系统”就是优先队列通常用二叉堆实现它将寻找最小值的操作从O(n)降到了O(log n)。所以解这道模板题你得到的不仅仅是一个ACAccepted的绿色对勾更是一套解决加权图最短路径问题的标准武器库堆优化的Dijkstra算法本身、高效存图的链式前向星技术以及对算法复杂度分析的深刻理解。接下来我将拆解这个“武器库”的每一个部件并分享从零实现到一次AC过程中的所有实战细节与避坑指南。2. 核心思路与算法选型解析面对最短路径问题我们有几个备选算法Floyd多源最短路O(n³)、Bellman-Ford能处理负权边O(VE)、SPFABellman-Ford的队列优化但最坏情况退化以及Dijkstra无负权边高效。题目明确是单源且无负权边Dijkstra是毋庸置疑的正解。但选择Dijkstra只是第一步关键在于选择哪一种Dijkstra。2.1 朴素Dijkstra为何在此处“失灵”朴素Dijkstra的流程非常清晰将节点分为“已确定最短距离”和“未确定”两个集合。每次从“未确定”集合中选出距离起点最近的节点将其标记为“已确定”并用它来松弛更新其所有邻居节点的距离。这个“选出最近节点”的操作在朴素实现中是通过遍历所有未确定节点来完成的复杂度为O(n)。对于稠密图边数接近n²这个开销可以接受因为更新边的操作本身也是O(n²)。但对于我们面对的稀疏图边数约等于节点数主要开销就浪费在了这O(n)次的遍历寻找上而真正有价值的松弛操作只有O(E)次。这就造成了性能的严重不匹配使得算法整体复杂度卡在O(n²)无法通过本题的数据规模。2.2 堆优化将“查找”转化为“维护”堆优化的思想精髓在于我们不再显式地维护“未确定”集合也不再每次都去遍历它。我们使用一个优先队列最小堆这个队列里存放的是一个个(距离, 节点)对。初始时只有起点(0, start)在队列中。算法的核心循环变为从堆顶弹出当前距离最小的节点对(dist, u)。如果dist大于我们此前记录到的节点u的最短距离dis[u]说明这个(dist, u)是一个“过时”的、无效的记录因为之前已经有更短的路径更新过u了直接跳过。否则用节点u去松弛它的所有邻居v。如果通过u到v的距离更短则更新dis[v]并将新的(dis[v], v)对压入堆中。这个过程中“查找最小距离节点”的操作变成了堆的弹出操作时间复杂度是O(log N)N为堆中元素数量。虽然同一个节点可能因为被多次松弛而多次入堆导致堆中元素总数可能大于节点数n但在稀疏图中这个数量级依然是O(E)的。因此算法的总时间复杂度可以优化到 O((nE) log n)对于稀疏图近似于 O(E log n)这是一个质的飞跃。2.3 图的存储为何选择链式前向星算法确定了数据的存储方式也至关重要。常见的存图方式有邻接矩阵和邻接表。邻接矩阵graph[u][v] w。查询任意边是否存在是O(1)但空间复杂度是O(n²)对于10^5的节点数需要10^10的量级完全不可行。邻接表使用vectorvectorpairint, intgraph[u]存储所有从u出发的边(v, w)。空间复杂度为O(nE)且遍历邻居非常方便。这是C中非常推荐的方式。链式前向星这是一种用数组模拟链表实现的邻接表。它相比vector实现的邻接表在内存访问上可能更连续常数时间更优尤其在竞赛极端卡常的场景下可能有微弱优势。其核心是三个数组head[maxn]存储每个节点第一条边的索引、edge[maxm]存储边的终点、next[maxm]和w[maxm]存储边权。虽然实现稍显复杂但作为一道模板题掌握链式前向星是很有价值的。对于本题使用vector邻接表完全足够且更易编写。但为了深入理解并完成“模板”的要求下文将同时给出链式前向星的实现。3. 核心细节解析与实现要点理解了算法思想我们开始着手实现。这里有几个关键的细节直接决定了代码的正确性和效率。3.1 数据结构的设计与初始化首先我们需要定义几个全局数组或容器dis[maxn]: 存储从起点到每个节点的当前最短距离。初始化为一个极大值如0x3f3f3f3f起点距离初始化为0。vis[maxn](可选): 在朴素Dijkstra中用于标记节点是否已确定。在堆优化版本中这个数组不是必须的因为我们通过判断从堆中弹出的距离是否等于dis[u]来过滤无效状态。但有些实现为了清晰仍会保留。图的存储结构如前所述选择vector或链式前向星。优先队列C中为priority_queue。默认是最大堆我们需要最小堆有两种方式存入负数pq.push({-dist, v})弹出时再取负。使用自定义比较函数或greaterpriority_queuepairint, int, vectorpairint, int, greaterpairint, int pq;。推荐第二种逻辑更清晰。注意事项一距离初始化的技巧使用memset(dis, 0x3f, sizeof(dis))来初始化dis数组为“无穷大”。0x3f3f3f3f是一个约等于10^9的数满足题目要求边权10^9并且其两倍仍在32位整数范围内不会溢出。这是一个竞赛中常用的技巧。3.2 堆优化Dijkstra的核心循环流程让我们用伪代码梳理最核心的循环这是算法的灵魂// 假设使用vector邻接表vectorvectorpairint, int graph(n1); // pairv, w // dis[] 已初始化 priority_queuepairint, int, vectorpairint, int, greaterpairint, int pq; dis[start] 0; pq.push({0, start}); // 存入 {距离 节点} while (!pq.empty()) { auto [dist_u, u] pq.top(); pq.pop(); // C17结构化绑定 // 关键过滤步骤如果弹出的距离大于当前记录的距离说明是旧数据跳过 if (dist_u dis[u]) { continue; } // 遍历u的所有出边 for (auto [v, w] : graph[u]) { int new_dist dis[u] w; if (new_dist dis[v]) { // 松弛操作 dis[v] new_dist; pq.push({new_dist, v}); // 注意这里可能会将同一个v的不同距离多次入堆 } } }注意事项二为什么需要“dist_u dis[u]”的判断这是堆优化Dijkstra最容易出错的地方。由于同一个节点v可能被多次松弛即多次发现更短路径我们会多次将(dis[v], v)压入堆中。但堆只能保证堆顶是最小值不能保证某个节点在堆中只出现一次。当较早的、较大的dist_v位于堆顶被弹出时此时dis[v]已经被后续更新的更小值覆盖了。这个弹出的(dist_v, v)就是一个“过时”的状态。如果不跳过它就会用这个过时的、较大的距离去松弛其他点导致错误。这个判断是保证算法正确性的关键。3.3 链式前向星的实现细节如果你决定挑战链式前向星以下是其实现模板struct Edge { int to; // 边的终点 int w; // 边权 int next; // 下一条边的索引 } edges[maxm]; // 边数组 int head[maxn]; // 头指针数组 int cnt 0; // 边计数器 // 加边函数添加一条从u到v权重为w的有向边 void addEdge(int u, int v, int w) { edges[cnt].to v; edges[cnt].w w; edges[cnt].next head[u]; // 新边指向原来u的头边 head[u] cnt; // 更新u的头边为新加的边 } // 遍历节点u的所有出边 for (int i head[u]; i ! 0; i edges[i].next) { int v edges[i].to; int w edges[i].w; // ... 进行松弛操作 }链式前向星的加边操作是“头插法”所以遍历时顺序与加边顺序相反但这对于最短路问题没有影响。4. 完整代码实现与逐行分析下面我将分别给出使用vector邻接表和链式前向星的两种AC代码并附上详细注释。4.1 方案一使用Vector邻接表推荐易写易读#include bits/stdc.h using namespace std; const int MAXN 100005; const int MAXM 200005; // 注意是无向边数组要开两倍 const int INF 0x3f3f3f3f; int n, m, s; int dis[MAXN]; // 使用vector存储图graph[u]是一个vector里面存的是pair终点v, 边权w vectorpairint, int graph[MAXN]; void dijkstra(int start) { // 1. 初始化距离数组 memset(dis, 0x3f, sizeof(dis)); dis[start] 0; // 2. 定义小顶堆优先队列元素为 pair当前距离, 节点编号 priority_queuepairint, int, vectorpairint, int, greaterpairint, int pq; pq.push({0, start}); // 3. 核心算法循环 while (!pq.empty()) { // 弹出当前距离起点最近的节点 auto [dist_u, u] pq.top(); pq.pop(); // 4. 关键判断如果弹出的距离大于当前记录的距离说明是旧数据跳过 if (dist_u dis[u]) { continue; } // 5. 使用u节点来松弛其所有邻居 for (auto edge : graph[u]) { int v edge.first; int w edge.second; int new_dist dis[u] w; // 如果找到更短的路径 if (new_dist dis[v]) { dis[v] new_dist; // 将新的状态放入堆中注意同一个v可能会被多次放入 pq.push({new_dist, v}); } } } } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); cin n m s; // 读入m条边构建图 for (int i 0; i m; i) { int u, v, w; cin u v w; // 添加有向边 u-v graph[u].push_back({v, w}); // 如果是无向图需要额外添加 v-u // graph[v].push_back({u, w}); } // 运行Dijkstra算法 dijkstra(s); // 输出结果 for (int i 1; i n; i) { if (dis[i] INF) { cout 0x7fffffff ; // 根据题目要求不可达输出2^31-1 } else { cout dis[i] ; } } return 0; }代码要点分析ios::sync_with_stdio(false); cin.tie(nullptr);是C关闭流同步的语句能显著加快大量数据输入输出的速度在竞赛中是标配。优先队列的类型声明较长但结构清晰priority_queue存储类型, 底层容器, 比较方式。松弛操作if (new_dist dis[v])是算法的核心逻辑只有找到更短路径时才更新并入堆。输出部分根据题目要求将不可达INF转换为2147483647输出。4.2 方案二使用链式前向星传统竞赛模板#include bits/stdc.h using namespace std; const int MAXN 100005; const int MAXM 200005; const int INF 0x3f3f3f3f; int n, m, s, cnt 0; int head[MAXN], dis[MAXN]; struct Edge { int to, w, next; } edges[MAXM]; // 链式前向星加边函数 void addEdge(int u, int v, int w) { edges[cnt].to v; edges[cnt].w w; edges[cnt].next head[u]; head[u] cnt; } void dijkstra(int start) { memset(dis, 0x3f, sizeof(dis)); dis[start] 0; priority_queuepairint, int, vectorpairint, int, greaterpairint, int pq; pq.push({0, start}); while (!pq.empty()) { auto [dist_u, u] pq.top(); pq.pop(); if (dist_u dis[u]) continue; // 遍历u的所有出边i从head[u]开始沿着next指针遍历 for (int i head[u]; i ! 0; i edges[i].next) { int v edges[i].to; int w edges[i].w; int new_dist dis[u] w; if (new_dist dis[v]) { dis[v] new_dist; pq.push({new_dist, v}); } } } } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); cin n m s; // 初始化head数组也可以不初始化因为cnt从0开始next0表示空 // memset(head, 0, sizeof(head)); for (int i 0; i m; i) { int u, v, w; cin u v w; addEdge(u, v, w); } dijkstra(s); for (int i 1; i n; i) { cout (dis[i] INF ? 0x7fffffff : dis[i]) ; } return 0; }链式前向星要点分析cnt从1开始计数这样head[u] 0天然表示没有出边遍历时for (int i head[u]; i; i edges[i].next)即可。加边函数addEdge是头插法新边的next指向原来的head[u]然后更新head[u]为新边。遍历时i是边的索引通过edges[i].to和edges[i].w获取终点和边权。5. 常见问题与实战调试技巧即便理解了算法第一次实现时也难免遇到各种问题。下面是我在实战和教学中总结的几个高频问题。5.1 为什么我的程序超时TLE这是最常见的问题。请按以下清单检查复杂度错误你是否错误地使用了朴素DijkstraO(n²)确认使用了优先队列。存图方式不当是否使用了邻接矩阵对于稀疏图务必使用邻接表或链式前向星。输入输出效率对于大量数据10^5级别是否使用了scanf/printf或关闭了流同步的cin/cout没有关闭同步的cin会很慢。容器选择优先队列是否正确定义为小顶堆使用greater或存入负数。无限循环或死循环检查图的遍历代码特别是链式前向星的next指针遍历确保终止条件正确。5.2 为什么我的程序答案错误WA没有过滤无效状态这是堆优化Dijkstra最经典的错误。务必在从堆中弹出元素后立即判断if (dist_u dis[u]) continue;。没有这一步算法就是错的。距离初始化问题dis数组是否初始化为足够大的值INF是否够大小于题目最大可能路径和输出不可达时是否按题目要求处理图是有向还是无向题目通常是有向图。如果错误地建成了无向图结果当然不对。仔细读题。数组越界节点编号是否从1开始MAXN和MAXM是否开得足够大无向图边数要开两倍。多组数据未重置如果是多组测试数据每次运行前是否重置了head、cnt、graph等全局变量5.3 关于堆中元素数量的疑问很多同学会担心“同一个节点多次入堆堆会不会变得巨大导致效率变低甚至内存超限” 理论上在最坏情况下如菊花图每个节点都可能入堆O(E)次堆的大小可能达到O(E)。但在实际竞赛数据中这种情况极少。O(E log E) 的复杂度是完全可以接受的。这也是为什么我们使用优先队列而不是手写二叉堆——STL的priority_queue效率足够高。如果实在担心可以使用配对堆__gnu_pbds::priority_queue其modify操作在某些情况下更优但本题完全不需要。5.4 调试与测试技巧小数据测试自己构造一个小图5-6个节点手动计算最短路径然后与程序输出对比。打印中间状态在算法循环中打印每次从堆中弹出的(u, dist_u)以及每次松弛操作观察算法的执行流程。对拍写一个朴素的、正确的但较慢的程序如Floyd或朴素Dijkstra用于小数据用随机生成的小规模数据同时运行两个程序比较输出是否一致。这是竞赛中验证算法正确性的黄金方法。边界测试测试 n1, m0 的情况测试起点就是终点的情况测试存在重边的情况题目通常允许重边应取最小边权。6. 算法扩展与性能思考掌握了这个模板你就能解决绝大多数无负权单源最短路问题。但学无止境我们可以思考得更深一些。6.1 如果存在负权边怎么办Dijkstra算法不能处理负权边因为它基于贪心策略认为“当前最短即全局最短”。一旦有负权边这个前提就不成立了因为后面可能通过负权边让路径变得更短。此时需要使用Bellman-Ford算法或其优化版本SPFA。但请注意SPFA在最坏情况下会退化到O(VE)因此除非题目明确说明可能有负权且数据经过特殊构造否则在竞赛中应优先使用Dijkstra。6.2 如何记录最短路径有时我们不仅需要距离还需要知道具体路径。这可以通过增加一个pre[maxn]数组来实现。在松弛操作成功时if (new_dist dis[v])不仅更新dis[v]同时记录pre[v] u。算法结束后从目标点t开始不断回溯pre[t]直到起点s即可得到逆序的路径。6.3 关于“模板”的再理解这道题被称作模板其意义在于它提供了一个经过充分优化的、可靠的算法实现框架。在实际比赛中遇到最短路径问题你几乎可以直接将这份代码的核心部分dijkstra函数和存图部分复制过去然后根据具体问题稍作修改比如处理多源、记录路径、结合其他条件等。它节省了你重新推导、调试基础算法的时间让你能更专注于问题本身的建模与转化。因此彻底理解并熟练“背诵”这个模板是算法竞赛学习中的一项重要基本功。最后我个人最深刻的体会是理解“为什么”比记住“怎么写”更重要。尤其是“过滤无效状态”那一步它不仅仅是代码里的一行if更是理解堆优化Dijkstra本质——它是在管理一个可能包含冗余状态的“候选集”——的关键。下次当你需要基于优先队列进行BFS式搜索时比如A*算法这种“状态管理”的思想会再次出现。把这个模板吃透它的价值会延伸到很多其他图论算法中去。

相关新闻

C++实战:从零构建文字冒险游戏“骗子酒馆”的完整指南

C++实战:从零构建文字冒险游戏“骗子酒馆”的完整指南

1. 项目概述:从“骗子酒馆”到C实战演练 最近在社区里看到不少朋友在讨论用C做些有趣的小项目来练手,从经典的贪吃蛇、俄罗斯方块,到一些需要点算法和设计模式支撑的复杂游戏。今天我想分享一个我个人觉得特别有意思的练手项目——“骗子酒馆…

2026/10/14 23:23:08 阅读更多 →
【系列:CCG Crypto CrackMe 逆向全解析 · 第 1 篇】

【系列:CCG Crypto CrackMe 逆向全解析 · 第 1 篇】

导读: 2001 年,CCG(China Cracking Group)的 Blowfish 放出了一个 CrackMe,声称"本题多解"。这个系列将完整记录破解它的全过程——从最基础的字节解析,到自定义壳的算法复原,到最后跑…

2026/9/30 7:32:24 阅读更多 →
STM32 HAL库驱动IIC段码屏实战:HT1621配置与软件模拟IIC详解

STM32 HAL库驱动IIC段码屏实战:HT1621配置与软件模拟IIC详解

1. 项目概述与核心价值 最近在做一个需要显示多路参数的小型设备,选来选去,最后用上了一块基于HT1621驱动芯片的LCD段码屏。这种屏成本低、功耗小,在温控器、电表、小家电上很常见。但实际驱动时发现,网上资料要么是51单片机的&am…

2026/10/5 18:39:15 阅读更多 →

最新新闻

Claude Code 安装配置完全指南:从Node环境到终端AI编程助手

Claude Code 安装配置完全指南:从Node环境到终端AI编程助手

简介:面向开发者的Claude Code安装配置代码包,聚焦智能终端助手在Windows、macOS、Linux三平台下的部署与集成,帮助读者完成Node.js环境准备、全局安装、API密钥配置,并快速接入Visual Studio Code与JetBrains IDE。包体共3个文件…

2026/10/14 23:23:41 阅读更多 →
在线火山图绘制全攻略:从双色到四色的参数与实操

在线火山图绘制全攻略:从双色到四色的参数与实操

1. 先看懂火山图:坐标轴、阈值线、颜色的底层逻辑很多人上来就找按钮,先问“火山图在哪里”。我的建议是,先用两分钟理解这张图的坐标和阈值在说什么。你知道了每个参数背后的含义,在线工具里的选项就不会让你犯迷糊,出…

2026/10/14 23:23:41 阅读更多 →
大模型训练数据管线全拆解:从清洗去重到Tokenize分片

大模型训练数据管线全拆解:从清洗去重到Tokenize分片

1. 从数据视角切入大模型训练:为什么值得深挖做模型训练的人都有一个共识:架构决定上限,数据决定下限。很多人拿到一个开源大模型,第一反应是去看它的网络结构——注意力怎么设计的、位置编码用的什么方案、归一化放在哪里。但真正…

2026/10/14 23:23:41 阅读更多 →
手写Tool Use的三种实战方案:从字符串解析到AST沙箱

手写Tool Use的三种实战方案:从字符串解析到AST沙箱

1. “手写 Tool Use”到底在考什么:面试官没说破的三层潜台词“面试官让我手写一个 Tool Use,我用了 3 种方案”——这个标题乍看像段程序员日常吐槽,但背后藏着当前大模型应用开发岗位最核心的能力筛选逻辑。我带过十几轮校招和社招技术面&a…

2026/10/14 23:23:41 阅读更多 →
智能体五类伤害与三方责任:风险控制与实操指南

智能体五类伤害与三方责任:风险控制与实操指南

1. 从“智能体闯祸”说起:为什么五类伤害与三方责任值得每个从业者吃透智能体这两年被聊得很多,从自动订票、自动写代码,到在业务系统里替人做决策、调资源、发指令,能力边界一路外扩。但真正在一线做过落地的人都知道&#xff0c…

2026/10/14 23:23:41 阅读更多 →
Delphi中用TPaintBox生成显示二维码,并保存为PNG回读Image的完整实践

Delphi中用TPaintBox生成显示二维码,并保存为PNG回读Image的完整实践

1. 从画布到文件:为什么用PaintBox而不是直接放Image最近在做桌面端工具时,遇到一个挺典型的交互需求:界面某处要根据数据动态生成二维码,当场显示给用户看,同时提供一个“保存图片”的按钮,把二维码落盘。…

2026/10/14 23:22:37 阅读更多 →

日新闻

AnyPS5通用适配层设计:兼容性与性能的工程取舍

AnyPS5通用适配层设计:兼容性与性能的工程取舍

1. 从"AnyPS5"这个名字说起:它到底想解决什么问题第一次看到"AnyPS5"这个标题,我脑子里冒出来的第一个念头是:这大概率是一个围绕"跨平台运行"或者"通用适配"做文章的项目。名字里的"Any"…

2026/10/14 0:00:41 阅读更多 →
Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

1. 项目概述:Flutter跨平台二手交易应用开发作为一名长期从事移动应用开发的工程师,我最近完成了一个基于Flutter框架的二手物品交易平台项目。这个项目最吸引我的地方在于它完美结合了Flutter的跨平台优势与HarmonyOS的生态特性,实现了"…

2026/10/14 0:00:41 阅读更多 →
DFS算法解决飞机降落调度问题实战

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:41 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/14 16:30:29 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 22:01:27 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 7:53:34 阅读更多 →