(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;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义