Books Exchange (hard version) CodeForces - 1249B2

題意:

有 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;
	}
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章