置换环。
i向a[i]连边,最终一定会连出一个环,有可能存在着一条链在后边跟这,这个环的长度一定要等于k才是满足题意的。
出现链的原因就是链在成环的路上被另一条成环的路覆盖了。
对于任何k >= 2的情况,链是可以任意长的,比如1 2被2 3覆盖, 2 3被 3 4覆盖,以此类推,只要它指向的那个环的长度等于k就是对的。
k=1的时候特判a[i] = i。
写的时候死活想不到特判,啊啊啊啊啊
#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define endl '\n'
using namespace std;
typedef pair<int, int> PII;
typedef long long ll;
const int N = 100010;
int n, k;
int a[N], lst[N];
int circle;
int st[N];
bool dfs(int u, int c)
{
st[u] = c;
int ne = a[u];
if(st[ne] && st[ne] != c)
{
return true;
}
else if(st[ne])
{
int last = u, cnt = 1;
while(last != ne)
{
last = lst[last];
cnt ++;
}
if(cnt == k)return true;
else return false;
}
lst[ne] = u;
dfs(ne, c);
}
void solve()
{
cin >> n >> k;
for(int i = 1; i <= n; i ++)
{
cin >> a[i];
st[i] = 0;
lst[i] = -1;
}
if(k == 1)
{
int f = 1;
for(int i = 1; i <= n; i ++)
{
if(a[i] != i)f = 0;
}
if(f)cout << "YES" << endl;
else cout << "NO" << endl;
return;
}
int cnt = 1;
for(int i = 1; i <= n; i ++)
{
if(st[i])continue;
if(!dfs(i, cnt ++))
{
cout << "NO" << endl;
return;
}
}
int f = 1;
for(int i = 1; i <= n; i ++)
{
if(!st[i])f = 0;
}
if(f)cout << "YES" << endl;
else cout << "NO" << endl;
}
int main()
{
IOS
int _;
cin >> _;
while(_ --)
{
solve();
}
return 0;
}