#P11405. 调试并查集

调试并查集

当前没有测试数据。

题目描述

zzx 最近新学习了一个数据结构:并查集。现在他正在做一道并查集练习题。下面是 zzx 写的并查集(确实是本人所写):

const int N=1001;
int n,fa[N];
void init()
{
    for(int i=1;i<=n;i++)fa[i]=i;
    return;
}
int find(int x){return fa[x]==x ? x : fa[x];}
void merge(int x,int y)
{
    if(find(x)==find(y))return;
    fa[find(x)]=find(y);
}

可以看到,他的代码中有路径压缩,但没有按秩合并。

现在 zzx 的代码挂在了某个大数据上。因为数据实在是太大了,他无法进行调试。所以他想知道他的并查集到底干了什么。具体来说,zzx 会给你一个初始的父亲数组 ff(即代码中的 fa,保证其可以通过先调用一次 setup(),再调用若干次 findmerge 得到)以及在代码结束时的父亲数组 gg。你需要构造出一种方案使得在只使用 findmerge 的前提下将 ff 变成 gg

输入格式

第一行一个正整数 TT,表示数据组数。每组数据将按如下方式给出:

第一行包含一个数,表示代码中的 nn

后面一行包含 nn 个正整数,表示 ff

后面一行包含 nn 个正整数,表示 gg

输出格式

对于每组数据,如果无法将 ff 变成 gg,输出一行 NO

否则先输出一行 YES,再输出一行一个整数 mm,表示操作次数。你需要保证 0m2×n20\leq m\leq 2\times n^2。可以证明,如果方案存在,则必定存在一个满足该条件的方案。

后面 mm 行,每行一个操作,按以下方式给出:

  • 1 x,表示调用函数 find(x)find(x)
  • 2 x y,表示调用函数 merge(x,y)merge(x,y)

你需要保证 1x,yn1\leq x,y\leq n

样例

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
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

数据范围

子任务 特殊性质 分值
1 n4n\leq 4 1010
2 n5n\leq 5
3 n6n\leq 6
4 n20n\leq 20 2020
5 保证 fi=if_i=i
6 3030

对于所有数据,$1\leq T\leq 10^5,3\leq n\leq 1000,\sum n^2\leq 5\times 10^6$。