并查集,在一些有N个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合中。这一类问题近几年来反复出现在信息学的国际国内赛题中,其特点是看似并不复杂,但数据量极大,若用正常的数据结构来描述的话,往往在空间上过大,计算机无法承受;即使在空间上勉强通过,运行的时间复杂度也极高,根本就不可能在比赛规定的运行时间(1~3秒)内计算出试题需要的结果,只能用并查集来描述。

并查集是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题。常常在使用中以森林来表示。

摘自网络↑

下面主要是自己的感悟emm可能有些不对的地方欢迎指出

并查集,顾名思义,方便的主要就是合并和查询两种基本操作,然后说一下并查集的基本操作:

fa[i]表示点i的父节点,根节点的父节点是它自己。

这里就涉及到初始化,因为开始的时候每一个点都是一棵独立的树,它们都是根节点,所以它们要把fa[i]=i。

另外sz[i]表示这一棵树的深度,只有根节点的sz值才是有效的,可能有些题目里不会涉及但是还是打上来哈

void init()
{
for(int i=1;i<=n;i++)
{
fa[i]=i;
sz[i]=1;
}
}

合并:

在实现合并操作之前, 我们先要想一个问题:合并两棵树,是不是把这两棵树上任意两个节点产生联系就可以了?

很明显不是。

我们的合并操作,应该是要把其中一整棵树都挂在另一棵树的根节点上,也就是把a树的根节点的父节点设置为b树的根节点,就完成了a,b两树的合并。

所以现在的问题是取根节点。

初始写法:

int get(int x)
{
if(fa[x]==x)
return x;
return get(fa[x]);
}

但是!如果这么写,每次查找根节点都要花费太多的时间,如果题目特殊构造一条链型的树,那么就会出现TLE.

怎么优化呢?

其实,在每次查找根节点所途径的路上遇到的所有节点,我们都可以把它们直接挂到根节点上,这样下次查找的时候就会方便许多了。

最终写法:

int get(int x)
{
if(fa[x]==x)
return x;
int r=get(fa[x]);
fa[x]=r;
return r;
}

那么接下来才是实现合并的操作。

所谓合并,就是如上所述,把其中一棵树的根节点挂到另一棵树的根节点上,实现合并,那么就很容易实现:

void merge(int x,int y)
{
int r1=get(x);
int r2=get(y);
if(r1==r2)
return;
fa[r1]=r2;
sz[r2]+=sz[r1];
}

sz数组的变化请自行理解(绝对不是懒得写 )

下一个,查找。

查找其实很简单,就是看两个节点的根节点是否相同,如果一样,那么就是在同一棵树上,否则就不是:

bool ask(int x,int y)
{
if(get(x)==get(y))return true;
else return false;
}

下面贴上完整代码:

#include<bits/stdc++.h>
using namespace std;
int n,fa[10001],z,x,y,m,sz[10001];
void init()
{
for(int i=1;i<=n;i++)
{
fa[i]=i;
sz[i]=1;
}
}
int get(int x)
{
if(fa[x]==x)
return x;
int r=get(fa[x]);
fa[x]=r;
return r;
}
void merge(int x,int y)
{
int r1=get(x);
int r2=get(y);
if(r1==r2)
return;
fa[r1]=r2;
sz[r2]+=sz[r1];
}
bool ask(int x,int y)
{
if(get(x)==get(y))return true;
else return false;
}
int main()
{
cin>>n>>m;
int fa[n];
init();
for(int i=1;i<=m;i++)
{
cin>>z>>x>>y;
if(z==1)
{
merge(x,y);
}
else
if(ask(x,y))cout<<"Y"<<endl;
else cout<<"N"<<endl;
}
return 0;
}

ov.

最新文章

  1. iOS 杂笔-如何解决tableview显示错乱问题
  2. 如何在ASP.NET Core中应用Entity Framework
  3. Android系统的五种数据存储形式(一)
  4. java虚拟机之引用
  5. 响应式web设计之CSS3 Media Queries
  6. 三步解决EntityFramework Code First中的MissingMethodException错误
  7. Nginx 伪静态教程
  8. jq select操作全集
  9. GetPrivateProfileStringA的文件名要小心写
  10. Keil 代码折叠功能的使用
  11. Easyui的combobox组件无法选择内容
  12. F - Truck History - poj 1789
  13. linux 自旋锁
  14. matlab GUI之常用对话框(一)-- uigetfile\ uiputfile \ uisetcolor \ uisetfont
  15. Zeppelin 用jdbc连接hive报错
  16. python词云的制作方法
  17. 百度编辑器Ueditor增加字体的修改方法
  18. PLSQL使用scott登录
  19. Alpha冲刺9
  20. kubernetes label 标签使用

热门文章

  1. SGI地址模式: O32, N32和N64
  2. [Erlang-0016][aque_tcp] 一个 Erlang TCP 组件
  3. 主要C++流派,看看你是哪一流
  4. 一个拼图工具TImageBox的制作思路
  5. rem.js移动布局实例教程
  6. 【linux杂谈】跟随大牛进行一次服务器间通讯问题的排查
  7. Laravel --- 自动生成数据
  8. U盘刻录kali linux启动盘提示找不到镜像解决方案
  9. Elasticsearch的使用
  10. 如何用 Flutter 实现混合开发?闲鱼公开源代码实例