You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CS50 Tideman算法lock_pairs函数循环问题求助

CS50 Tideman算法lock_pairs函数循环问题修复

错误含义解析

你提到的两个问题本质是对Tideman算法核心逻辑的误解:

  • 不会跳过形成循环的最后一对:当处理到某一对时,添加它会让整个图刚好形成闭环(比如已有A→B、B→C,处理C→A时),你的代码没有跳过这对,反而执行了错误的锁定操作,导致循环保留。
  • 不会跳过形成循环的中间一对:比如已有A→B、C→A,处理B→C时,添加这对会直接形成循环,但你的代码未正确检测,依然锁定了该对,导致循环出现。

Tideman算法的核心规则是:按配对优先级从高到低处理每一对,只有当添加当前配对不会形成循环时,才锁定该配对;如果会形成循环,直接跳过该配对,不做任何锁定。你的代码逻辑完全颠倒,检测到循环时反而去锁定多条边,这是根本错误。

修复方案

1. 修正循环检测逻辑

首先确保isCycle函数的作用是:判断从起点出发,是否能通过已锁定的边到达目标点。正确的isCycle实现示例如下:

bool isCycle(int start, int target) {
    // 如果当前起点就是目标,说明存在路径
    if (start == target) {
        return true;
    }
    // 遍历所有候选人,检查是否有已锁定的边从start指向其他节点
    for (int i = 0; i < candidate_count; i++) {
        if (locked[start][i]) {
            // 递归检查下一个节点能否到达目标
            if (isCycle(i, target)) {
                return true;
            }
        }
    }
    return false;
}

2. 重写lock_pairs函数

按照算法规则,遍历每一对时,仅当添加该对不会形成循环(即从loser无法回到winner)时,才锁定该配对:

void lock_pairs(void)
{
    for (int i = 0; i < pair_count; i++)
    {
        int winner = pairs[i].winner;
        int loser = pairs[i].loser;
        // 检查:若锁定winner→loser后,loser能否通过已锁定路径回到winner
        // 若不能形成循环,则锁定该配对
        if (!isCycle(loser, winner))
        {
            locked[winner][loser] = true;
        }
        // 若会形成循环,直接跳过,不执行任何锁定操作
    }
}

关键逻辑说明

  • 循环检测的核心是:尝试添加当前配对后,判断是否存在从loser到winner的路径。如果存在,说明添加该配对会让图出现闭环,必须跳过;如果不存在,说明该配对可以安全锁定,不会破坏图的有向无环结构。
  • 你原代码中的while循环完全多余,Tideman算法不需要在检测到循环时去锁定其他边,只需跳过当前配对即可。

内容的提问来源于stack exchange,提问作者Gabriele Simoncini

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 18:34:52