CF1833E Round Dance

我们用并查集求最大值,然后看有多少个没有闭环的并查集(有邻居数<=2的就是未闭环),设未闭环的总共有num个。若num>0,那么答案就是cnt-num+1个。注意每一次要状态恢复

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int T;
int n;
int a[N];
int p[N];
int find(int x)
{
	if(p[x]==x)
	{
		return x;
	}
	return p[x]=find(p[x]);
}
void merge(int x,int y)
{
	int rx=find(x),ry=find(y);
	if(rx!=ry)
    {
        p[rx]=ry;
    }
}
set<int> g[N];
map<int,int> mp;
struct node
{
	set<int> t;
}q[N];
int minx;
int main()
{
	int T;
	cin>>T; 
	while(T--)
	{
		cin>>n;
		for(int i=1;i<=n;i++)
		{
			p[i]=i;
			g[i].clear();
            q[i].t.clear();
		}
		for(int i=1;i<=n;i++)
		{
			cin>>a[i];
			merge(i,a[i]);
			g[i].insert(a[i]);
			g[a[i]].insert(i);
		}
		int cnt=0;
        mp.clear();
		for(int i=1;i<=n;i++)
		{
			if(p[i]==i)
			{
				cnt++;
				mp[p[i]]=cnt;
			}
		}
		for(int i=1;i<=n;i++)
		{
			int rt=find(i);
			q[mp[rt]].t.insert(i);
		}
		int num=0;
		for(int i=1;i<=cnt;i++)
		{
			bool flag=false; 
			for(const auto& elem : q[i].t)
			{
				if(g[elem].size()<2)
				{
				    flag=true;
                    break;
				}
			}
			if(flag)
			{
			    num++;
			}
			
		}
        minx=0;
		if(num>=2)
		{
		    minx=cnt-(num-1);
		}
		else
		{
		    minx=cnt;
		}
		cout<<minx<<' '<<cnt<<endl;
	}
	
	
	
	
	
	return 0;
}
posted @ 2026-02-19 20:57  曾翎一  阅读(0)  评论(0)    收藏  举报