(Day3)并查集

并查集

并查集,就是看谁和谁是一伙的,加入到同一棵树中。

代码要点:

//找到一个结点根结点的函数
int fin(int x)
{
    if(rt[x]==x)return x;
    return rt[x]=fin(rt[x]);//快速查找
}

//把每一个序号的父结点改为自身
for(int i = 0;i < n;i ++)
{
    rt[i] = i;
}

while(k--)
{
    cin>>x>>y;
  	int xx = fin(x);//如果想把两个结点放在同一个树中,需要获取两个结点的根结点,然后把两棵树连在一起
    int yy = fin(y);
    if(xx!=yy)
    {
        rt[yy]=xx;
        num[xx]+=num[yy];
    }

}

例题:(近模板题)

http://poj.org/problem?id=1611

题目大意:有n个人,m个小组,每个人可以加入多个小组。先输入n和m,之后的m行,先输入一个数表示小组有几个人,然后输入成员的编号。输出一共有多少人感染。每次默认0号是感染的。小组内频繁交流

思路:每次把一个小组后面的所有人连到第一个人上,比较省时间,连就完事了。

时隔4年之后再次写这道题,写的方法居然比之前的用时少多了。

AC代码:

#include<cstdio>
#include<algorithm>
#include<iostream>
using namespace std;
const int N = 3e4+9;
int n,m,k,x,y;
int rt[N];
int num[N];
int fin(int x)
{
    if(rt[x]==x)return x;
    return rt[x]=fin(rt[x]);
}
int main()
{
    while(cin>>n>>m)
    {
        if(n==0&&m==0)break;
        
        for(int i = 0;i < n;i ++)
        {
            rt[i] = i;
            num[i] = 1;//存储以i为根结点的树有多少个结点
        }
           
        while(m--)
        {
            cin>>k>>x;
            int xx = fin(x);//第一个只用查一次就好,其它的挂在第一个上面
            k--;
            while(k--)
            {
                cin>>y;
                int yy = fin(y);
                if(xx!=yy)
                {
                    rt[yy]=xx;
                    num[xx]+=num[yy];//继承yy的结点数
                }
            }
        }
        int zz = fin(0);
        cout<<num[zz]<<endl;
        
    }
    return 0;
}

posted @   wlqtc  阅读(9)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
点击右上角即可分享
微信分享提示