836. 合并集合

836. 合并集合
思路:
开始时每个集合都是一个独立的集合,并且都是等于自己本身下标的数
例如:
p[5]=5,p[3]=3;
如果是M操作的话那么就将集合进行合并,合并的操作是:
p[3]=p[5]=5;
所以3的祖宗节点便成为了5
此时以5为祖宗节点的集合为{5,3}
如果要将p[9]=9插入到p[3]当中,应该找到3的祖宗节点,
然后再把p[9]=9插入其中,所以p[9]=find(3);(find()函数用于查找祖宗节点)
也可以是p[find(9)]=find(3),因为9的节点本身就是9
此时以5为祖宗节点的集合为{5,3,9};
如果碰到多个数的集合插入另一个集合当中其原理是相同的
例如:
上述中以5为祖宗节点的是p[5],p[3],p[9];(即p[5]=5,p[3]=5,p[9]=5)
再构造一个以6为祖宗节点的集合为{6,4,7,10}
如果要将以6为祖宗节点的集合插入到以5为祖宗节点的集合,则该操作可以是
p[6]=find(3)(或者find(9),find(5))
此时p[6]=5
当然如果是以6为祖宗节点集合中的4,7,10则可以这样
p[find(4)]=find(3)
或者p[find(7)]=find(3)均可以
此时以6为祖宗节点的集合的祖宗节点都成为了5

代码:

# include<iostream>
using namespace std;

const int N = 100010;
int p[N];
int n,m;

int find(int x)
{
    if(p[x] != x) p[x] = find(p[x]);
    /*
    经上述可以发现,每个集合中只有祖宗节点的p[x]值等于他自己,即:
    p[x]=x;
    */
    return p[x];
    //找到了便返回祖宗节点的值
}

int main()
{
    cin >> n >> m;
    for(int i = 1;i <= n;i++) p[i] = i;
    while(m--)
    {
        char op[2];
        int a,b;
        scanf("%s %d %d",&op,&a,&b);
        if(*op == 'M') p[find(a)] = find(b);//集合合并操作
        else 
        {
            if(find(a) == find(b)) puts("Yes");//如果祖宗节点一样,就输出yes
            else puts("No");
        }
    }
    
    
    return 0;
}
上一篇:【Rust】宏-DRY


下一篇:关于一些网络协议的思考