题解:洛谷 P2913 Wheel Rotation

【题目来源】

洛谷:P2913 [USACO08OCT] Wheel Rotation G - 洛谷

【题目描述】

Farmer John has an old-time thresher (wheat harvester) that requires belts to be installed on various gears to turn the parts. The engine drives pulley 1 in a clockwise direction which attaches via a belt to pulley 2. Pulley 2 attaches via a belt to pulley 3 and so on through a total of N (2 <= N <= 1,000) pulleys (and N-1 belts).

The diagram above depicts the two ways a belt can be installed between two gears. In this illustration, pulley 1's belt directly drives pulley 2 (a 'straight' connection) and thus they will rotate in the same direction. Pulley 3 drives pulley 4 via a 'crossed belt' that reverses the direction of the rotation.

Given a list of the belt types that connect the pulleys along with the fact that pulley 1 is driven in a clockwise direction by the engine, determine the drive direction of pulley N. Each belt is described by three integers:

* S_i -- the driving (source) pulley
* D_i -- the driven (destination) pulley
* C_i -- the connection type (0=straight, 1=crossed)
Unfortunately, FJ lists the belts in random order.
By way of example, consider the illustration below. N = 4, and pulley 1 is driven clockwise by the thresher engine. Straight
belts drive pulley 2 and then pulley 3, so they rotate clockwise. The crosswise belt reverses the rotation direction so pulley 4 (pulley N) rotates counterclockwise.

POINTS: 70
约翰有一个过时的收割机,需要在它的各种滑轮上装配皮带才能让收割机的各个部分运作起来。引擎能够驱动滑轮1向顺时针方向转动,滑轮1通过一条皮带又连接到滑轮2。滑轮2又通过一 条皮带连接到滑轮3,等等,总共有N(2 <= N <= 1000)个滑轮和N - 1条皮带。

皮带连接两个滑轮有两种方式:直接连接和交叉连接。直接连接的两个滑轮旋转方向相同,即同为顺时针或同为逆时针。交叉连接的两个滑轮旋转方向相反。

现在给出一个列表,里面列出所有皮带的连接方式。已经知道滑轮1被引擎驱动着向顺时针方 向转动。每一条皮带由下面三个数定义:

•驱动滑轮S,输入驱动力的滑轮。

•被驱动滑轮D;,被驱使转动的滑轮。

•连接类型C,0表示直接连接,1表示交叉连接。

不幸的是,约翰的这个列表中,皮带的顺序是混乱的。所以请你写一个程序来求出滑轮N的 转动方向。

【输入】

* Line 1: A single integer: N

* Lines 2..N: Each line describes a belt with three integers: S_i, D_i, and C_i

【输出】

* Line 1: A single integer that is the rotation direction for pulley N (0=clockwise, 1=counterclockwise)

【输入样例】

4
2 3 0
3 4 1
1 2 0

【输出样例】

1

【核心思想】

  1. 问题分析:给定 \(N\) 个滑轮和 \(N-1\) 条皮带,每条皮带连接驱动滑轮 \(S_i\) 和被驱动滑轮 \(D_i\),连接类型 \(C_i\)\(0\)(直接连接,方向相同)或 \(1\)(交叉连接,方向相反)。皮带顺序混乱,已知滑轮 \(1\) 顺时针转动,求滑轮 \(N\) 的转动方向。这是一个拓扑排序/按源点排序模拟问题,关键在于按驱动滑轮编号排序后,从 \(1\)\(N-1\) 依次传递方向。

  2. 算法选择

    • 按源点排序:将皮带按 \(S_i\) 从小到大排序,确保处理第 \(i\) 条皮带时,其驱动滑轮的方向已确定
    • 方向传递:直接连接时 \(a[D_i] = a[S_i]\),交叉连接时 \(a[D_i] = !a[S_i]\)\(0\)\(1\)\(1\)\(0\)
  3. 关键步骤

    • 初始化\(a[1] = 0\)(顺时针)
    • 读取输入\(N\)\(N-1\) 条皮带 \((S_i, D_i, C_i)\)
    • 排序:按 \(S_i\) 升序排列皮带
    • 方向传递\(i\)\(1\)\(N-1\)):
      • \(C_i = 0\)\(a[D_i] = a[S_i]\)
      • \(C_i = 1\)\(a[D_i] = !a[S_i]\)
    • 输出 \(a[N]\)
  4. 时间/空间复杂度

    • 时间复杂度:\(O(N \log N)\),排序主导
    • 空间复杂度:\(O(N)\),存储皮带和方向数组
  5. 按源点排序模拟的核心思想

    • 链式结构特性\(N\) 个滑轮 \(N-1\) 条皮带形成链状结构(树形,但度为 \(1\) 的节点是端点),从 \(1\)\(N\) 存在唯一路径
    • 排序保证处理顺序:按 \(S_i\) 排序后,处理皮带 \(i\) 时其驱动端的方向必然已计算(因为链从 \(1\) 开始延伸)
    • 布尔翻转:交叉连接用逻辑非 ! 实现方向反转,简洁高效
    • 适用于"链式传递 + 乱序输入"类问题,核心是通过排序恢复正确的处理顺序

【解题思路】

【算法标签】

普及- #其他排序

【代码详解】

#include <bits/stdc++.h>
using namespace std;
int n;
struct node {
    int s, d, c;
}p[1005];
bool cmp(node a, node b) {
    return a.s < b.s;
}
int a[1005];
int main()
{
    a[1] = 0;  // 第1个轮的方向为顺时针
    cin >> n;  // 输入n
    for (int i=1; i<n; i++) {  // 遍历n-1对数据
        cin >> p[i].s >> p[i].d >> p[i].c;  // 记录每2个齿轮的S、D和C
    }
    sort(p+1, p+n, cmp);  // 按照齿轮编号从小到大排序
    for (int i=1; i<=n; i++) {  // 遍历n-1对数据
        if (p[i].c==0) {  // 如果直接连接
            a[p[i].d] = a[p[i].s];  // D轮的方向与S轮的方向相同
        } else {  // 如果是交叉连接
            a[p[i].d] = !(a[p[i].s]);  // D轮的方向与S轮方向相反
        }
    }
    cout << a[n];  // 输出最后一个轮的方向
    return 0;
}

【运行结果】

4
2 3 0
3 4 1
1 2 0
1
posted @ 2026-08-28 15:55  团爸讲算法  阅读(2)  评论(0)    收藏  举报