Day5

这段代码是 SPFA 算法(Shortest Path Faster Algorithm),而且是一个专门用于判断负环的 SPFA 版本。

我们可以通过以下三个“铁证”断定它不是 Dijkstra:

  1. vis 数组的逻辑: 在 Dijkstra 中,vis 意味着“最短路已确定,不再更改”;而这里的 vis 是配合 q.push 使用的,意味着“该点是否已在队列中”。
  2. ++cnt[v] >= n 这是判定负环的杀手锏,Dijkstra 无法判定负环。
  3. 队列类型: 虽然代码中没写 q 的定义,但配合 !vis[v] 的入队逻辑,这个 q 一定是一个普通的 std::queue

核心代码逐行拆解

1. 遍历邻居

for(int i=head[u]; i!=-1; i=e[i].nxt)
{
    v = e[i].to, w = e[i].val;
  • 这部分通过链式前向星找到从点 u 连出的所有邻居 v 和边权 w
  • 注意:这里你的 head 初始化是 -1,所以循环条件是 i != -1

2. 松弛操作 (Relaxation)

    if(dis[v] > dis[u] + w)
    {
        dis[v] = dis[u] + w;
  • 这是所有最短路算法的核心:如果通过 u 走到 v 发现比原来的路径更短,就更新 dis[v]

3. 入队与判重 (The Queue Logic)

        if(!vis[v]) // 如果点 v 不在当前的队列里
        {
            vis[v] = true; // 标记它已经进队了
            ...
            q.push(v); // 把它丢进队列
        }
  • 关键区别: 在 SPFA 中,如果一个点的距离变短了,它就有可能去更新它的邻居。但如果它已经在队列里等待处理了,我们就没必要再把它放进去一次。
  • 这就是 if(!vis[v]) 的作用:防止队列中出现大量重复的点,优化性能。

4. 负环判定 (Negative Cycle Detection)

            if(++cnt[v] >= n)
            {
                printf("YES\n"); // 发现负环!
                return;
            }
  • 原理: 在一个含有 \(n\) 个点的图中,任意两点间的最短路径最多只包含 \(n-1\) 条边。
  • 如果点 v 的入队次数(或者说被更新次数)达到了 \(n\) 次,说明它被卷入了一个权值为负的环。在这个环里,路越走越短,永远没有尽头。
  • 一旦满足这个条件,算法立即终止并报告“有负环”。

总结:这段代码的运行流程

  1. 从队列取出点 u
  2. 遍历 u 的所有邻居 v
  3. 如果 v 变短了:
    • 更新 v 的距离。
    • 检查 v 是否已经在队列里。
    • 如果不在队列:
      • v 的入队次数 +1
      • 如果入队次数 \(\ge n\):报告“有负环”并退出。
      • v 标记为在队列中,并压入队列。
  4. u 处理完,出队,并将 vis[u] 设为 false(表示以后 u 如果再变短,还能再进队)。

为什么 Dijkstra 不能这样写?

Dijkstra 每次选的是“当前全局最短”的点,它默认每个点处理一次就结束了。而 SPFA 允许点反复入队,正是这种反复入队的特性,让它能够检测出那些由于负环而导致距离不断缩小的异常情况。


2. dist[n] == INF 这句话的意义是什么?

在算法开始前,我们将所有点到起点的距离都设为 INF(无穷大)。这代表:“在还没开始找路之前,我认为所有点都是不可达的。”

  • 如果存在路径:Dijkstra 算法会不断“松弛”边。只要有一条路能通向 ndist[n] 就会被更新成一个具体的、比 INF 小的数值(比如 10 或 100)。
  • 如果不存在路径:如果起点和终点根本不连通(比如图是断开的),那么 dist[n] 就永远不会被更新,它会一直保持初始值 INF

所以,if (dist[n] == INF) 是在做一个判定

  • 成立:说明从 1 号点出发,无论如何也走不到 \(n\) 号点。按照题目要求,输出 -1
  • 不成立:说明 dist[n] 已经变成了一个具体的距离,路径是存在的,可以放心去重建并输出。

总结

  • dist 数组告诉你:能不能到,以及最短多远
  • pre 数组告诉你:具体怎么走
posted @ 2026-01-26 13:57  EcSilvia  阅读(4)  评论(0)    收藏  举报