Codeforces Round 897 (Div. 2) D
不是很难的题目,没做出来但是。
使得\(a_{l_i}=l_{(i\mod k)+1}\)这个操作我第一眼没看明白,读题不够仔细,没看到\(l\)只有k给个数字。导致我开始的时候思路错了一段时间,其实还挺要命的,因为第一次没想到,后面要再想到就有点麻烦了。
这题的特点就是在于这个等式。可以发现,这个其实是一个类似于环的东西,我们每次操作如果是选择了一个我完整的\(l\),那把\(l_i连向l_{(i\mod k)+1}\)就一定会形成一个环,除非是被其他的部分覆盖了。但是最后的操作是一定不会被覆盖的,也就是,我对每个\(a[i]\),把\(i向a[i]\)连接一条边,从上面的操作的式子里面可以发现,这个就是\(l_i连向l_{(i\mod k)+1}\)。所以如果是这样操作得到的图,里面必定含环,而且,这个环的大小一定是k。我们可以发现,每个点只能有一个出边,所以这个图的形态就很明显了。
我这些点其实都是想到了的,但是没有把他们联系起来。没有联系起来的原因其实就是对条件想的不够多。要手玩一会,加深理解就能i昂到。主要就是题目的特性。建图不是什么难想到的,还是很明显的暗示的。
读题要读仔细,适当的手玩有助于解题。记住了。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline int read() {
char c=getchar();int a=0,b=1;
for(;c<'0'||c>'9';c=getchar())if(c=='-')b=-1;
for(;c>='0'&&c<='9';c=getchar())a=a*10+c-48;return a*b;
}
int head[200001],tot,a[200001];
struct edge
{
int next,to;
}e[200001];
inline void add(int i,int j)
{
e[++tot].next=head[i];
e[tot].to=j;
head[i]=tot;
}
int deg[200001],Size[200001],ans=0;
void dfs(int x,int fa)
{
// cout<<x<<endl;
for(int i=head[x];i!=0;i=e[i].next)
{
int u=e[i].to;
if(u==fa)continue;
if(Size[u]!=0||deg[u]==0)continue;
deg[u]--;
Size[u]=Size[x]+1;
// cout<<Size[u]<<endl;
ans=max(ans,Size[u]);
dfs(u,x);
}
}
int main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
int T=read();
while(T--)
{
for(int i=1;i<=tot;i++)head[i]=0;
tot=0;
int n=read(),k=read();
for(int i=1;i<=n;i++)
{
a[i]=read();
add(i,a[i]);
}
bool no=0;
if(k==1)
{
for(int i=1;i<=n;i++)
{
if(a[i]!=i)
{
no=1;break;
}
}
if(no)cout<<"No"<<endl;
else cout<<"Yes"<<endl;
continue;
}
for(int i=1;i<=n;i++)deg[i]=0,Size[i]=0;
for(int i=1;i<=n;i++)
{
for(int j=head[i];j!=0;j=e[j].next)
{
int u=e[j].to;
deg[u]++;
}
}
queue<int> q;
for(int i=1;i<=n;i++)
if(deg[i]==0)
q.push(i);
while(!q.empty())
{
int x=q.front();
q.pop();
for(int i=head[x];i!=0;i=e[i].next)
{
int u=e[i].to;
deg[u]--;
if(deg[u]==0)
q.push(u);
}
}
for(int i=1;i<=n;i++)
{
if(deg[i]==0)continue;
Size[i]=1;
ans=0;
dfs(i,0);
if(ans!=k)
{
no=1;
break;
}
}
if(no)cout<<"No"<<endl;
else cout<<"Yes"<<endl;
}
return 0;
}