浏览器标题切换
浏览器标题切换end

CodeForces1249B1/B2-Books Exchange-dfs-一般搜索+记忆化搜索

一般搜索

注意:一般定义成void

Books Exchange (easy version)   CodeForces - 1249B2 

The only difference between easy and hard versions is constraints.

There are nn kids, each of them is reading a unique book. At the end of any day, the ii-th kid will give his book to the pipi-th kid (in case of i=pii=pi the kid will give his book to himself). It is guaranteed that all values of pipi are distinct integers from 11 to nn (i.e. pp is a permutation). The sequence pp doesn't change from day to day, it is fixed.

For example, if n=6n=6 and p=[4,6,1,3,5,2]p=[4,6,1,3,5,2] then at the end of the first day the book of the 11-st kid will belong to the 44-th kid, the 22-nd kid will belong to the 66-th kid and so on. At the end of the second day the book of the 11-st kid will belong to the 33-th kid, the 22-nd kid will belong to the 22-th kid and so on.

Your task is to determine the number of the day the book of the ii-th child is returned back to him for the first time for every ii from 11 to nn.

Consider the following example: p=[5,1,2,4,3]p=[5,1,2,4,3]. The book of the 11-st kid will be passed to the following kids:

  • after the 11-st day it will belong to the 55-th kid,
  • after the 22-nd day it will belong to the 33-rd kid,
  • after the 33-rd day it will belong to the 22-nd kid,
  • after the 44-th day it will belong to the 11-st kid.

So after the fourth day, the book of the first kid will return to its owner. The book of the fourth kid will return to him for the first time after exactly one day.

You have to answer qq independent queries.

Input

The first line of the input contains one integer qq (1q10001≤q≤1000) — the number of queries. Then qq queries follow.

The first line of the query contains one integer nn (1n21051≤n≤2⋅105) — the number of kids in the query. The second line of the query contains nn integers p1,p2,,pnp1,p2,…,pn (1pin1≤pi≤n, all pipi are distinct, i.e. pp is a permutation), where pipi is the kid which will get the book of the ii-th kid.

It is guaranteed that n2105∑n≤2⋅105 (sum of nn over all queries does not exceed 21052⋅105).

Output

For each query, print the answer on it: nn integers a1,a2,,ana1,a2,…,an, where aiai is the number of the day the book of the ii-th child is returned back to him for the first time in this query.

Example

Input
6
5
1 2 3 4 5
3
2 3 1
6
4 6 2 1 5 3
1
1
4
3 4 1 2
5
5 1 2 4 3
Output
1 1 1 1 1 
3 3 3 
2 3 3 2 1 3 
1 
2 2 2 2 
4 4 4 1 4 


题意:
给出t组数,每组给出n,表示接下来有n本书,a[i]=k,表示第i个人需要把手上的书给第k个人。
问:编号为i的书回到第i个人手里需要多少次。


看第二组样例输入2 3 1,输出3 3 3。
  • sum1=0,
        第1个人把手上的书给第2个人,sum++,第二个人把书给第3个人,sum++,第三个人把书给第1个人,sum++,所以sum1=3;
  • sum2=0,
   第2个人把手上的书给第3个人,sum++,第3个人把书给第1个人,sum++,第1个人把书给第2个人,sum++,所以sum2=3;
  • sum3=0,
   第3个人把手上的书给第1个人,sum++,第1个人把书给第2个人,sum++,第2个人把书给第3个人,sum++,所以sum3=3;


思路:

开一个for循环,然后dfs(i,i,1)
i:第i个人
i:第i个人所对应下次把书传到a[i]手上去
1:代表书转手次数=1,第一次书在自己手上,所以次数为1,以后每次搜索次数++

开始进行搜索
void dfs(int x,int k,int t)//传入下标x,下标k,转手次数t
 {
     if(w)
         return;//剪枝
     if(x==a[k])//此时表示第x个人找到了对应a[k]=x的书
     {
         w=t;//定义w为全局变量,w=t,记录转手次数
         return ;
     }
     dfs(x,a[k],t+1);//否则还未找到,继续进行搜索
 }



代码如下:
 1 #include<stdio.h>
 2 int a[220],w;
 3 
 4 void dfs(int x,int k,int t)
 5 {
 6     if(w)
 7         return;
 8     if(x==a[k])
 9     {
10         w=t;
11         return ;
12     }
13     dfs(x,a[k],t+1);
14 }
15 
16 int main()
17 {
18     int t,m;
19     scanf("%d",&t);
20     while(t--)
21     {
22         int n;
23         scanf("%d",&n);
24         for(int i=1;i<=n;i++)
25             scanf("%d",&a[i]);
26         for(int i=1;i<=n;i++)
27         {
28             w=0;
29             dfs(i,i,1);
30             printf("%d ",w);
31         }
32         printf("\n");
33     }
34     return 0;
35 }

 

 

记忆化搜索

注意:一般定义成int,需要有返回值,表示之前已经搜到过的值,无需再搜

Books Exchange (hard version)  CodeForces - 1249B2 

The only difference between easy and hard versions is constraints.

There are nn kids, each of them is reading a unique book. At the end of any day, the ii-th kid will give his book to the pipi-th kid (in case of i=pii=pi the kid will give his book to himself). It is guaranteed that all values of pipi are distinct integers from 11 to nn (i.e. pp is a permutation). The sequence pp doesn't change from day to day, it is fixed.

For example, if n=6n=6 and p=[4,6,1,3,5,2]p=[4,6,1,3,5,2] then at the end of the first day the book of the 11-st kid will belong to the 44-th kid, the 22-nd kid will belong to the 66-th kid and so on. At the end of the second day the book of the 11-st kid will belong to the 33-th kid, the 22-nd kid will belong to the 22-th kid and so on.

Your task is to determine the number of the day the book of the ii-th child is returned back to him for the first time for every ii from 11 to nn.

Consider the following example: p=[5,1,2,4,3]p=[5,1,2,4,3]. The book of the 11-st kid will be passed to the following kids:

  • after the 11-st day it will belong to the 55-th kid,
  • after the 22-nd day it will belong to the 33-rd kid,
  • after the 33-rd day it will belong to the 22-nd kid,
  • after the 44-th day it will belong to the 11-st kid.

So after the fourth day, the book of the first kid will return to its owner. The book of the fourth kid will return to him for the first time after exactly one day.

You have to answer qq independent queries.

Input

The first line of the input contains one integer qq (1q10001≤q≤1000) — the number of queries. Then qq queries follow.

The first line of the query contains one integer nn (1n21051≤n≤2⋅105) — the number of kids in the query. The second line of the query contains nn integers p1,p2,,pnp1,p2,…,pn (1pin1≤pi≤n, all pipi are distinct, i.e. pp is a permutation), where pipi is the kid which will get the book of the ii-th kid.

It is guaranteed that n2105∑n≤2⋅105 (sum of nn over all queries does not exceed 21052⋅105).

Output

For each query, print the answer on it: nn integers a1,a2,,ana1,a2,…,an, where aiai is the number of the day the book of the ii-th child is returned back to him for the first time in this query.

Example

Input
6
5
1 2 3 4 5
3
2 3 1
6
4 6 2 1 5 3
1
1
4
3 4 1 2
5
5 1 2 4 3
Output
1 1 1 1 1 
3 3 3 
2 3 3 2 1 3 
1 
2 2 2 2 
4 4 4 1 4 

思路:
由于数据变大了,所以按照上面的方法进行深搜会超时,所以需要用到记忆化搜素。
开一个book数组,book[x]=w,表示书回到第x个人手上需要转手w次。
假设输入2 3 1,a[i]=k的书回到第k个人手中需要t次的话,那么在转手过程中所经过的所有点k回到第k个人手中也需要t次,
所以开一个b数组,把所经过的所有k全部保存下来,for循环往下走走到该点就不需要再搜,直接输出即可
利用book数组,把b数组里面存的所有数(有p个)通过循环赋值为k,即book[ b[i] ]=w。


代码如下:

 1 #include<stdio.h>
 2 #include<string.h>
 3 const int N=2e5+20;
 4 int a[N],w,b[N],p,book[N];
 5 
 6 void dfs(int x,int k,int t)
 7 {
 8     if(x==a[k])
 9     {
10         w=t;
11         book[x]=w;
12         return;
13 //        return book[x]=t;
14     }
15     b[p++]=a[k];//把走过的点全部存起来,下次碰到不用再走就不会超时
16     dfs(x,a[k],t+1);
17 }
18 
19 int main()
20 {
21     int t,n;
22     scanf("%d",&t);
23     while(t--)
24     {
25         memset(book,0,sizeof(book));
26         scanf("%d",&n);
27         for(int i=1;i<=n;i++)
28             scanf("%d",&a[i]);
29         for(int i=1;i<=n;i++)
30         {
31             p=0;
32             if(i!=1)
33                 printf(" ");
34             if(book[i])
35             {
36                 printf("%d",book[i]);
37                 continue;
38             }
39            // w=0;
40             dfs(i,i,1);
41             for(int j=0;j<p;j++)
42                 book[b[j]]=w;
43             printf("%d",w);
44         }
45         printf("\n");
46     }
47     return 0;
48 }

 

posted @ 2019-10-28 23:35  抓水母的派大星  阅读(295)  评论(0编辑  收藏  举报