題意:
有 n 人, 每個人都正在讀一本獨一無二的小h書. 在每一天的結束的時候, 都會進行一次py交易,交易規則爲:第 i 的人將給他的書給第 pi 的人 (如果i=pi,那麼就是給他自己). 默認pi都是不同的數,是一個1到n的排列. 並且這個p是固定的,不隨時間的改變而改變.
例如, 如果 n=6 並且 p=[4, 6, 1, 3, 5, 2],那麼第一天結束的時候進行了第一次py交易, 第1個人的書給了第4個人, 第2個人的書給了第6個人,依次類推.。第二天結束的時候,又進行了一次py交易,第1個人的書在第3個人的手裏(因爲第4個人給了第3個人), 第2個人的書又回到了自己這裏(因爲第6個人又給了第2個人),依次類推 .
你的任務是確定在第幾天后,第i個人的書回到了他自己本身。
例如這個樣例: p = [5, 1, 2, 4, 3]. 第一個人的書交易過程如下:
第一天結束的時候第1個人給了第5個人
第二天結束的時候第5個人給了第3個人
第三天結束的時候第3個人給了第2個人
第四天結束的時候第2個人給了第1個人
所以4天后, 第一個人的書回到了他自己本身這裏。 第四個人的書1天之後就回到了自己本身(因爲當i=4的時候,i=pi)。
你需要回答q個詢問
題解:最終回到他自己說明一定成環,用一個環上每個點到自己的距離都是一樣的(都等於周長),所以記憶化搜索降低時間複雜度(ps:自己剛開始只想每次都用一次memset(vis,0,sizeof(vis)去對每一個點判環並記錄,毫無疑問超時了。。。。)
代碼:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn=1e6+5;
int p[maxn],ans[maxn],vis[maxn],temp;
int dfs(int i,int cnt) {
vis[i]=1;
if(vis[p[i]]) {
return ans[i]=cnt+1;
}
else return ans[i]=dfs(p[i],cnt+1);
}
int main() {
ios::sync_with_stdio(false);
int n,t;
cin>>t;
while(t--) {
memset(ans,0,sizeof(ans));
memset(vis,0,sizeof(vis));
cin>>n;
for(int i=1; i<=n; i++)cin>>p[i];
for(int i=1; i<=n; i++) {
if(!vis[i])dfs(i,0);
}
for(int i=1; i<=n; i++)
cout<<ans[i]<<" ";
cout<<endl;
}
}