#C1017. 并查集

并查集

并查集(set)

【题目描述】

对于一个长度为 nn 值域为 [1,n]Z[1,n]\cap Z 的数组 ff,定义以下两个操作:

  1. 有返回值的 find(x)find(x) 操作(1xn1 \le x \le n):
    • fx=xf_x = x:返回 xx
    • 否则,返回进行 find(fx)find(f_x) 操作并将返回值记为 rootroot,令 fxrootf_x \gets root,并返回 rootroot
  2. 无返回值的 merge(x,y)merge(x,y) 操作(1x,yn1 \le x,y \le n):
    • 进行 find(x)find(x) 操作并令返回值为 xx',进行 find(y)find(y) 操作并令返回值为 yy'
    • fxfyf_{x'} \ne f_{y'},让 fxyf_{x'} \gets y'

给定两个长度为 nn 的数组 aabb,能否通过 2×n22\times n^2 次以内的上述两个操作将 aa 变成 bb,若可行给出构造方案(保证 aabb 都可以从一个 bi=i\forall b_i=i 的数组通过若干次上述操作得到)

【输入格式】

本题单个测试点有多组测试数据。

set.in 输入数据。

第一行一个整数 TT 表示数据组数。

对于每组数据:

第一行一个整数 nn

接下来一行 nn 个整数表示 aa

接下来一行 nn 个整数表示 bb

【输出格式】

输出数据到 set.out

对于每组数据,若无法满足则输出一行 NO

否则,第一行输出 YES

接下来一行一个整数 mm 表示你的操作次数。

接下来 mm 行每行表示操作,每个操作按一下方式输出:

  • 1 x:调用 find(x)find(x)
  • 2 x y:调用 merge(x,y)merge(x,y)

如果有多种方案请输出任意一种。

【样例 1 输入】
5
3
1 2 3
2 2 3
4
1 2 3 3
1 1 1 2
5
1 2 3 4 5
2 3 4 5 5
5
1 1 1 1 1
1 2 3 4 5
6
1 2 2 4 5 6
1 1 5 1 4 2
【样例 1 输出】
YES
1
2 1 2
YES
4
2 3 2
1 4
2 2 1
1 3
YES
4
2 1 2
2 1 3
2 2 4
2 3 5
NO
YES
7
2 6 2
2 2 5
1 3
2 2 4
1 2
2 2 1
1 2
【样例 2】

见选手目录下的 set/set2.inset/set2.ans

该样例满足测试点 11 的约束条件。

【样例 3】

见选手目录下的 set/set3.inset/set3.ans

该样例满足测试点 8,9,108,9,10 的约束条件。

【数据范围】

对于 100%100\% 的数据,满足 1T1051 \le T \le 10^51n10001 \le n \le 1000n25×106\sum n^2 \le 5 \times 10^6ai[1,n]\forall a_i \in [1,n]bi[1,n]\forall b_i \in [1,n]

测试点编号 特殊性质
11 n4n \le 4
22 n5n \le 5
33 n6n \le 6
4,54,5 n20n \le 20
6,76,7 ai=i\forall a_i=i
8,9,108,9,10

【提示】

下发了个 checker.cpp,保证与评测使用的完全不相同不保证能正常运行。一般上是这么用的:

打开 powershell,进入当前文件夹;

编译:g++ checker.cpp -o checker -std=c++14 -Wall -O2

运行:./checker set.in set.out set.ans set.in 是输入文件,set.out 是输出文件,set.ans 是答案文件。

过了会输出 AC,没过不会输出 AC。