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;
}

posted @ 2024-04-16 19:37  HL_ZZP  阅读(12)  评论(0编辑  收藏  举报