返回题解分享
讨论 / 题解分享/ 帖子详情

传送阵(编程题) - 题解

#include <bits/stdc++.h>
#define int long long
using namespace std;
typedef pair<int,int> pii;
const int N=1000000+10;
int n,ans;
int a[N],fa[N],cnt[N];
void init()
{
    for(int i=1;i<=n;i++)
    {
        fa[i]=i;
        cnt[i]=1;
    }
}
int find(int x)
{
    if(fa[x]==x) return x;
    else return fa[x]=find(fa[x]);
}
void union_(int x,int y)
{
    x=find(x);
    y=find(y);
    if(x!=y)
    {
        fa[x]=y;
        cnt[y]+=cnt[x];
    }
}
void solve()
{
  cin>>n;
  init();
  for(int i=1;i<=n;i++)
  {
      cin>>a[i];
      union_(i,a[i]);
  }
  for(int i=1;i<=n;i++)
  {
      ans=max(ans,cnt[find(i)]);
      if(find(i)!=find(i+1))
      {
          ans=max(ans,cnt[find(i)]+cnt[find(i+1)]);
      }
  }
  cout<<ans;
}
signed main()
{
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  int t;
  t=1;
  // cin>>t;
  while(t--)
  {
    solve();
  }
  return 0;
}
2 回复 0 转发 0 喜欢 12 阅读
回复 (2)
默认 最新
露米 2026/4/1
看到你分享的题解了,谢谢你。

并查集的运用很熟练,路径压缩和集合大小的统计逻辑写得很清晰,代码整体看起来非常整洁。我注意到你在最后统计答案时,考虑了通过连接相邻位置来合并两个连通块的情况,这个切入点抓得很准。

有一个温馨的小提醒:在 for 循环里,当 i 到达 n 时,find(i+1) 可能会访问到数组定义范围之外(即下标为 n+1 的位置)。如果在循环边界上稍微处理一下,或者给数组多留一点空间,代码运行起来会更稳健一些。

另外,如果题目允许在任意两个不连通的集合间建立连接,而不不仅限于相邻的点,你觉得统计逻辑会不会有更有趣的变化呢?

很开心能看到这样的分享,如果刷题过程中有了新的灵感,欢迎随时再来交流。慢慢积累,你已经做得很棒了 🙂
如果在解题过程中还有其他想尝试的思路,或者在调试时遇到了小卡点,随时都可以找我聊聊。

我会一直在这里为你打气的,加油 🙂
0
露米 2026/3/19
谢谢你分享这道题的思路。

用并查集来维护连通块并统计集合大小,代码逻辑写得很清晰。这种处理连通性问题的方式确实非常高效。

我注意到你在最后统计答案时,尝试计算了相邻两个位置 ii+1 所属集合的大小之和。这大概是题目中允许在相邻点之间建立某种特殊的“连接”来合并两个传送网络吧?

有一个小细节想和你交流一下:当循环到 i = n 时,find(i+1) 可能会访问到数组边界之外。如果能稍微处理下这个边界,代码运行起来会更稳健一些。

另外,这道题如果允许在任意两个不连通的点之间建立一次连接,思路会不会有不一样的变化呢?期待看到你更多的思考 🙂
加油,期待你的下一篇分享。如果在刷题过程中有了新的灵感,也欢迎随时发帖分享,大家一起进步呀 🙂
0