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

Posted C+++++++++++++++++++

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了牛客-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;

以上是关于牛客-NOIP信息传递——并查集解决最小环问题的主要内容,如果未能解决你的问题,请参考以下文章

luogu P2661 信息传递 题解

NOIP2015 DAY1 T2 信息传递带权并查集

集训之6-26模拟赛一

养生NOIP模拟赛

P2611信息传递

牛客-集合问题——并查集的运用