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

 

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