题解:P12123 [蓝桥杯 2024 省 B 第二场] 传送阵
刚学并查集来试试手
题目对传送阵的描述让我们知道,每个输入的 \(a_i\) 与 \(i\) 之间可任意传送,所以可以先用并查集合并。
进行遍历时,如果不使用魔法,则找到最长集合的长度,就是答案;如果使用了魔法,那么就要找出相邻两个元素所在集合的长度和的最大值。
理清思路,我们需要完成一下几步:
- 并查集的操作,就是将输入的 \(a_i\) 与 \(i\) 置于一个集合之中;
- 遍历得到最长集合的长度;
- 遍历得到相邻两个元素所在集合的长度和的最大值;
- 输出以上两步得出的两个值的最大值。
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;
}
感谢阅读!
本文来自博客园,作者:Circle_Table,转载请注明原文链接:https://www.cnblogs.com/Circle-Table/articles/19177406

浙公网安备 33010602011771号