题解:洛谷 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
【核心思想】
-
问题分析:给定 \(N\) 个滑轮和 \(N-1\) 条皮带,每条皮带连接驱动滑轮 \(S_i\) 和被驱动滑轮 \(D_i\),连接类型 \(C_i\) 为 \(0\)(直接连接,方向相同)或 \(1\)(交叉连接,方向相反)。皮带顺序混乱,已知滑轮 \(1\) 顺时针转动,求滑轮 \(N\) 的转动方向。这是一个拓扑排序/按源点排序模拟问题,关键在于按驱动滑轮编号排序后,从 \(1\) 到 \(N-1\) 依次传递方向。
-
算法选择:
- 按源点排序:将皮带按 \(S_i\) 从小到大排序,确保处理第 \(i\) 条皮带时,其驱动滑轮的方向已确定
- 方向传递:直接连接时 \(a[D_i] = a[S_i]\),交叉连接时 \(a[D_i] = !a[S_i]\)(\(0\) 变 \(1\),\(1\) 变 \(0\))
-
关键步骤:
- 初始化:\(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]\)
-
时间/空间复杂度:
- 时间复杂度:\(O(N \log N)\),排序主导
- 空间复杂度:\(O(N)\),存储皮带和方向数组
-
按源点排序模拟的核心思想:
- 链式结构特性:\(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
浙公网安备 33010602011771号