牛客-NOIP信息传递——并查集解决最小环问题

题目

题目连接

题目详解

上面的手写已经很详细了,我这里做个总结:

这是一个最小环问题。

此法限制条件:每个点的出度必须为1(方便计算环里面的结点个数)

具体做法:

  • 用并查集思路做每条边的连接。

    //TODO 并查集的查找动作,查找的同时记一波数
    int find(int i,int& cnt){
        cnt++;
        if(i==f[i])return i;
        return find(f[i],cnt);//TODO 注意为了方便每次能查找根结点的同时计算这个环上的元素个数,所以不要去路径压缩!
    }
    
    ...
    f[i] = dst;//TODO 由于数据给出i的传递对象是dst,所以把i的出度设为dst    
    ...
    
  • 一旦出现连接dst会产生环,则更新环的大小(这里利用所有元素出度为1的性质简化了判环和计算环元素个数的过程)。

    //TODO 并查集的查找动作,查找的同时记一波数
    int find(int i,int& cnt){
        cnt++;
        if(i==f[i])return i;
        return find(f[i],cnt);//TODO 注意为了方便每次能查找根结点的同时计算这个环上的元素个数,所以不要去路径压缩!
    }
    
    ...
    if(find(dst,cnt)==i){//TODO 一旦产生出度为0的点连接了他的子节点(只要这个结点的根结点是i,则这个结点时i的子节点),则产生环
       ret = min(cnt,ret);
    } 
    ...
    

解题代码

#include<bits/stdc++.h>
#define MAXN 200005
using namespace std;
int f[MAXN];
//TODO 并查集的查找动作,查找的同时记一波数
int find(int i,int& cnt){
    cnt++;
    if(i==f[i])return i;
    return find(f[i],cnt);
}
int main(){
    ios::sync_with_stdio(false);
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)
        f[i] = i;
    int ret = INT_MAX;
    for(int i=1;i<=n;i++){
        int dst,cnt = 0;
        cin>>dst;
        if(find(dst,cnt)==i){//TODO 一旦产生出度为0的点连接了他的子节点则产生环
            ret = min(cnt,ret);
        }else{//TODO 没有产生环则,正常连接
            f[i] = dst;
        }
    }
    cout<<ret;
    return 0;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值