编组站是连接或拆分列车车厢以对列车进行维护和保养的场所。编组站中存在可供列车移动的轨道。我们将用图来表示轨道上列车车厢的位置。图中的每一条边表示一节列车车厢所处的状态,因此,一列列车可以表示为图上的一条路径。此时,路径上的所有顶点和边都必须互不相同。特别地,题目中给定的图始终是一棵树。
列车可以沿着轨道移动。列车的移动是分阶段进行的,在一个阶段中,列车一端的车厢会移动到相邻的另一条边上。具体地,对于表示列车的路径 $P$,一次移动的结果是:将 $P$ 的一端顶点所相邻且不在 $P$ 中的一条边及其对应的顶点加入到 $P$ 中,同时从另一端将对应的顶点和边从 $P$ 中移除,从而得到一条新的路径(见图1)。注意,在每一个阶段中,路径的长度保持不变。
图1
给定分别表示初始列车位置和最终列车位置的两条长度为 $m$ 的路径 $P$ 和 $Q$。路径的长度指路径中包含的边的数量。这里,路径 $P$ 与 $Q$ 不共享任何边。换言之,不存在同时被 $P$ 和 $Q$ 经过的边。我们需要通过移动路径 $P$,使其最终变为路径 $Q$。在此过程中,需要找到最少的移动阶段数。
给定一棵包含 $n$ 个顶点的树 $T$,以及分别表示初始列车和最终列车的长度为 $m$ 的路径 $P$ 和 $Q$,请编写程序判断是否可以将 $P$ 移动到 $Q$,如果可以,则输出最少的移动阶段数。
例如,在图2中给定了两条互不共享任何边、长度为 2 的路径 $P$ 和 $Q$。如图所示,可以在 5 个阶段内将路径 $P$ 移动到 $Q$,并且这是最少的移动阶段数。
实现细节
你需要为管理员实现以下两个函数:
函数说明
void init(int n, vector<int> X, vector<int> Y);- 该函数在最初被调用,且只会被调用一次。树的顶点数为 $n$,顶点编号为 $1$ 到 $n$。 $X$ 和 $Y$ 是大小为 $n-1$ 的 vector,树中的每一条边表示为 $(X[i], Y[i])$。
long long train(vector<int> Z);- $Z$ 是大小为 4 的 vector,表示初始路径 $P$ 的两个端点 $Z[0]$ 和 $Z[1]$,以及最终路径 $Q$ 的两个端点 $Z[2]$ 和 $Z[3]$。 该函数需要返回将 $P$ 移动到 $Q$ 的最少阶段数;如果无法移动,则返回 $-1$。
提交要求
你必须提交且仅提交一个名为 train.cpp 的文件。该文件中必须实现以下两个函数:
void init(int n, vector<int> X, vector<int> Y);long long train(vector<int> Z);
上述函数的行为应与前文描述完全一致。当然,你可以自行定义并在内部使用其他函数。提交的代码不得进行输入输出操作,也不得访问其他文件。
输入格式(grader 示例)
给定的 grader 按如下格式读取输入:
- 第 1 行:$n\ q$ ($n$ 为树的顶点数,$3 \le n \le 250{,}000$,顶点编号为 $1$ 到 $n$; $q$ 为查询次数,$1 \le q \le 250{,}000$)
- 接下来的 $n-1$ 行:每行两个整数 $x\ y$,表示树中的一条边 $(x, y)$,$1 \le x \ne y \le n$
- 接下来的 $q$ 行:每行四个整数 $a\ b\ c\ d$,表示初始路径 $P$ 的两个端点 $a, b$,以及最终路径 $Q$ 的两个端点 $c, d$ 所有查询中给定的路径 $P$ 的长度之和 $\le 1{,}000{,}000$
grader 会输出函数 train 的返回值;如果无法移动,则输出 $-1$。
子任务
子任务 1(11 分)
- $n \le 80$,$q \le 80$
子任务 2(18 分)
- 路径 $P$ 的长度 $\le 2$
子任务 3(34 分)
- 路径 $P$ 的长度 $\le 100$
- 所有路径 $P$ 的长度之和 $\le 250{,}000$
子任务 4(36 分)
- $n \le 1{,}000$,$q \le 1{,}000$
子任务 5(51 分)
- 无额外限制
样例数据
输入样例 1
11 2 1 2 3 2 4 3 4 5 6 5 8 4 7 8 8 9 10 9 11 10 3 5 7 4 3 6 7 10
输出样例 1
3 7
下面展示了样例 1 中函数调用及其返回结果:
init(11, {1, 3, 4, 4, 6, 8, 7, 8, 10, 11}, {2, 2, 3, 5, 5, 4, 8, 9, 9, 10})train({3, 5, 7, 4})返回3train({3, 6, 7, 10})返回7