专栏文章
题解:CF1327D Infinite Path
CF1327D题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @mioxdyzl
- 此快照首次捕获于
- 2025/12/03 02:42 3 个月前
- 此快照最后确认于
- 2025/12/03 02:42 3 个月前
这类有类似置换操作的题,第一反应应该是直接建图。后面默认是从 到 连边建图。
现在我以样例2为例举个例子。
下图分别是是 ,, 中的一个环。

发现规律了吗?对于图 的某个环来说,其每条边都相当于是图 向前走了 步。设此环在 中的长为 , 和 最大公约数为 ,则环上模 同余的点在 上一定在同一个环上。
那么思路就非常简单了。先找环,然后枚举最大公约数 , 找出这个环上所有新环是否颜色相同,更新答案。
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 条评论,欢迎与作者交流。
正在加载评论...