1 条题解

  • 0
    @ 2025-10-30 10:48:19

    题目理解

    我们有一个由 NN 个齿轮和 MM 条链条(边)组成的传动系统。
    每条边 (u,v,x,y)(u, v, x, y) 表示:

    • 如果 uuxx 圈,那么 vvyy 圈。
    • 传动比 x:yx:y 的符号表示方向:
      • 正:uu 顺时针 → vv 顺时针
      • 负:uu 顺时针 → vv 逆时针

    换句话说,我们可以把齿轮的转动用一个实数 rir_i 表示(可以是任意实数,表示转速或角度),对于每条边 (u,v,x,y)(u, v, x, y),应满足:

    rurv=yx \frac{r_u}{r_v} = \frac{y}{x}

    因为 uuxx 圈对应 vvyy 圈,所以 rux=rvyr_u \cdot x = r_v \cdot y 的另一种写法是 ru/rv=y/xr_u / r_v = y / x


    转化为图论问题

    我们可以把每个齿轮 ii 看作图的一个节点,链条是边。
    对于边 (u,v,x,y)(u, v, x, y),我们得到约束:

    rux=rvy r_u \cdot x = r_v \cdot y

    即:

    rurv=yx \frac{r_u}{r_v} = \frac{y}{x}

    如果我们设 r1=1r_1 = 1(作为参考),那么我们可以用 BFS 或 DFS 遍历图,推导出所有 rir_i 相对于 r1r_1 的值。

    具体来说,从节点 uu 到节点 vv 的传递关系是:

    已知 rur_u,则 rv=ruxyr_v = r_u \cdot \frac{x}{y}(注意这里 xx 是正整数,yy 是非零整数,可能是负数)。


    检查相容性

    当我们遍历图时:

    1. 如果某个节点还没有被访问过,就按上述公式计算它的 rr 值。
    2. 如果某个节点已经被访问过,就检查当前计算出的 rr 值是否与之前的值一致(考虑浮点数精度问题,可以用分数形式避免精度误差)。

    关键:由于 yy 可能是负数,所以传动比可能是负的,表示转动方向相反。
    在计算中,负号会导致 rr 的正负号变化,表示转动方向。

    如果所有推导出的 rr 值都满足所有边的约束,则输出 Yes,否则 No


    实现细节

    • 为了避免浮点数精度问题,我们可以用分数表示 rir_i(num,den)(num, den),即 ri=num/denr_i = num/den,并且保持最简分数形式(用 gcd 约分)。
    • 符号由分子分母的符号共同决定。
    • 检查一致性时,比较两个分数是否相等:num1den2==num2den1num1 \cdot den2 == num2 \cdot den1
    • 注意负数情况。

    算法步骤

    1. 读入 TT
    2. 对每组数据:
      • 建图(邻接表),存储 (to,x,y)(to, x, y)
      • 初始化 vis[]vis[] 为 false,ratio[]ratio[] 为未定义。
      • 从节点 1 开始 BFS/DFS,设 ratio[1]=(1,1)ratio[1] = (1, 1)
      • 遍历过程中,对于边 (u,v,x,y)(u, v, x, y)
        • 如果 vv 未访问,则 ratio[v]=ratio[u](x,y)ratio[v] = ratio[u] \cdot (x, y) 并约分。
        • 如果 vv 已访问,则检查 ratio[u]y==ratio[v]xratio[u] \cdot y == ratio[v] \cdot x 是否成立,不成立则返回 No
      • 如果所有边都相容,输出 Yes
    • 1

    信息

    ID
    4745
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者