专栏文章

题解:CF1327D Infinite Path

CF1327D题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@mioxdyzl
此快照首次捕获于
2025/12/03 02:42
3 个月前
此快照最后确认于
2025/12/03 02:42
3 个月前
查看原文
这类有类似置换操作的题,第一反应应该是直接建图。后面默认是从 pip_iii 连边建图。
现在我以样例2为例举个例子。
下图分别是是 p1p^1p2p^2p3p^3 中的一个环。
发现规律了吗?对于图 pkp^k 的某个环来说,其每条边都相当于是图 p1p^1 向前走了 kk 步。设此环在 p1p^1 中的长为 mmmmkk 最大公约数为 dd,则环上模 dd 同余的点在 pkp^k 上一定在同一个环上。
那么思路就非常简单了。先找环,然后枚举最大公约数 dd, 找出这个环上所有新环是否颜色相同,更新答案。

Code

CPP
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e6+10;
int n,p[N],c[N];
bool v[N];
int cnt;
vector<int>circle[N];
int ans,m,a[N];
void dfs(int x){//找环
	if(v[x])return ;
	v[x]=1;
	circle[cnt].push_back(c[x]);
	dfs(p[x]);//因为其实(i,pi)连边建图和(pi,i)连边建图等价,所以这么写较为简便
}
int num[N];
void work(){
	for(int d=1;d<=m;d++){
		if(m%d!=0)continue;
		for(int i=0;i<d;i++)num[i]=0;
		for(int i=1;i<=m;i++){
			int x=i%d;
			if(num[x]==0)num[x]=a[i];
			else if(num[x]!=a[i])num[x]=-1;
		}
		bool p=0;
		for(int i=0;i<d;i++){
			if(num[i]!=-1){p=1;break;}
		}
		if(p){
			ans=min(ans,d);
			return ;
		}
	}
}
signed main(){
	ios::sync_with_stdio(false);cin.tie(0);
	int T;cin>>T;
	while(T--){
		cin>>n;
		for(int i=1;i<=n;i++)cin>>p[i];
		for(int i=1;i<=n;i++)cin>>c[i];
		ans=1145141919810ll;
		for(int i=1;i<=n;i++)v[i]=0;
		cnt=0;
		for(int i=1;i<=n;i++){
			if(!v[i]){
				cnt++;circle[cnt].clear();
				dfs(i);
			}
		}
		for(int i=1;i<=cnt;i++){
			m=circle[i].size();
			ans=min(ans,m);
			for(int j=1;j<=m;j++)a[j]=circle[i][j-1];
			work();
		}
		cout<<ans<<"\n";
	}
	return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...