题解:P12123 [蓝桥杯 2024 省 B 第二场] 传送阵

刚学并查集来试试手

题目传送门

题目对传送阵的描述让我们知道,每个输入的 \(a_i\)\(i\) 之间可任意传送,所以可以先用并查集合并。

进行遍历时,如果不使用魔法,则找到最长集合的长度,就是答案;如果使用了魔法,那么就要找出相邻两个元素所在集合的长度和的最大值。

理清思路,我们需要完成一下几步:

  1. 并查集的操作,就是将输入的 \(a_i\)\(i\) 置于一个集合之中;
  2. 遍历得到最长集合的长度;
  3. 遍历得到相邻两个元素所在集合的长度和的最大值;
  4. 输出以上两步得出的两个值的最大值。

Code

#include <bits/stdc++.h>
#define ios ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
using namespace std;
int n,a[1000005],f[1000005],l[1000005];//l[i]记录传送阵i所在集合长度
int x,y,ans;

//并查集
int find(int x){
	if(x==f[x])return x;
	return f[x]=find(f[x]);
}
void merge(int x,int y){
	int fx,fy;
	fx=find(x);fy=find(y);
	if(fx!=fy)f[fy]=fx,l[fx]+=l[fy];
}

int main(){
	ios;cin>>n;
	for(int i=1;i<=n;i++){
		f[i]=i;l[i]=1;
	}
	for(int i=1;i<=n;i++){
		cin>>a[i];
		merge(i,a[i]);
	}
	for(int i=1;i<=n;i++){
		ans=max(ans,l[find(i)]);
		//找到最大的集合
	}
	for(int i=1;i<n;i++){
		x=find(i);y=find(i+1);
		if(x!=y){
			ans=max(ans,l[x]+l[y]);
			//存在两个相邻的传送阵,无法直接到达
			//此时所能到达的总数为这两个传送阵所在集合的长度之和
		}
		
	}
	cout<<ans;
	return 0;
}

感谢阅读!

posted @ 2025-10-30 16:13  Circle_Table  阅读(5)  评论(0)    收藏  举报