这题补了好久。。最开始感觉很简单,然后发现自己低估了这题难度。。
https://oj.neu.edu.cn/problem/1507
题意:给定一个1到N的排列P_1到P_N, 请判断是否存在一个由N个点,N-1条边构成的无向连通图,满足对于任意两个整数i和j(1<=i,j<=N且i!=j),若第i个点和第j个点之间有边相连,则第P_i个点和第P_j个点之间同样有边相连。
思路:把置换拆成循环,在两个长度为a和b的循环之间连边会连出lcm(a,b)条边,只有循环节长度相整除的环才可能连边(否则必然会导致出现环),把环大小排序,充要条件是第一个环长度是1或2且后头的环长是第一个的倍数。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
int p[maxn];
int ori,cnt;
vector<int> vec;
bool vis[maxn];
int find(int x){
vis[x] = 1,++cnt;
if(p[x]==ori) return cnt;
else find(p[x]);
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t;
while(cin>>t){
for(int i=1;i<=t;i++){
cin>>p[i];
}
memset(vis,0,sizeof vis);
vec.clear();
for(int i=1;i<=t;i++){
if(!vis[i]) ori=i,cnt=0,vec.push_back(find(ori));
}
sort(vec.begin(),vec.end());
int ans = 0;
if(vec[0]==1) ans = 1;
else if(vec[0]==2){
ans = 1;
for(int i=0;i<vec.size();i++){
if(vec[i]%2) ans = 0;
}
}
else ans = 0;
if(ans) puts("Yes");
else puts("No");
}
return 0;
}