题目大意:
每人有一个编号和序号i,编号是从1到n。
每个人也有一本书,需要将书给编号为i的人。
问:经过几次交换书会到自己手上。
Input:
第一行:q (1 <= q <= 1000),q个问题。
第二行:n (1 <= n <= 2e5),n个人。
第三行:n个数,每个人手中的序号。
Output:
n个数,每个数表示当前编号的人经过几次交换拿到原来的书。
核心代码:
分析:
假设序号为5 1 2 4 3
1 -> 5 -> 3 -> 2 -> 1
所以第一个人需要4次交换可以拿到原来的书。
若将这个链写成环,可以发现环上的数交换的次数相同。根据这个特点可以简化搜索。
void dfs(int i, int pos) //i目标编号,pos当前人的编号
{
s++; //每次进dfs就让搜索次数加1,因为最小交换次数是1。
if (p[pos] == i) //当前人的编号与目标相同
{
ans[pos] = s; //进dfs的人
return; //注意一定要返回!返回到上一层dfs处,因为环上的人还没有放答案
}
else //当前编号与目标不同
{
dfs(i,p[pos]); //继续向下搜索
ans[pos] = s; //环上的人
}
}