算法痕迹---并查集

模板

1.初始化

2.找根节点

3.合并

int per[1100];
void init(){
	for(int  i =1; i <= N; ++i)
		per[i] = i;//初始化  起初每一个节点都是独立的 父节点是本身
}
int find(int x)
{
	if(x == per[x])//递归
		return x;
	return per[x] = find(per[x]);
}
//能够简写成
//return x==per[x]?

x:per[x]=find(per[x]);
void join (int x, int y){//合并两个节点
	int fx = find(x);
	int fy = find(y);
	if(fx != fy)//假设x。y的根节点不同
		per[fx] = fy;//把两个根节点连接
}//至于哪个和哪个节点连接,看深度,能够开个数组。把深度小的连到深度大的,这是一种优化方式。数据大的时候能够用

find函数 寻找根节点还有两种实现方法:

int find(int x)
{
	int r = x;
	while(r != per[r])
		r = per[r];//更新节点 直到r=per[r]  (根节点的父节点是其本身 )
	int i ,j;
	i = x;
	while(i != r){//路径压缩
		j = per[i];//把下一个节点保存一下 ,也就是当前节点的父节点
		per[i] = r;//把当前这个节点的父节点赋值为根节点
		i = j;//更新节点
	}
	return r;//返回根节点
}
//或
int find(int x)
{
	int r = x;
	while(r != per[r])
		r = per[r];
	per[x] = r; //令r是x的父节点 一步到位}  

以下是递归优化路径合并:

void join (int x, int y)
{
    int fx = find(x);
    int fy = find(y);
    if(fx == fy)
        return ;
    if(ran[fx] < ran[fy])//将深度小的树合并到深度大的数如果两棵树的深度各自是h1,h2
        per[fx] = fy;//则合并后的数的高度h:max(h1,h2),if h1<>h2
    else{            //h1+h2,if h1=h2
        per[fy] = fx;
        if(ran[fx] == ran[fy]) ran[fx]++;
    }
}
时间: 2024-08-01 06:27:22

算法痕迹---并查集的相关文章

算法模板——并查集 2(支持快速即时查询本连通块内容,纯原创!)

实现功能:输入N,现在有N个数:接下来输入任意行,如果是"1 x y"则表示把x和y所在的块合并:如果是"2 x"则表示输出x所在的块的全部内容 原理:其实主要是自己创造了一个可并链line,he表示链头,ta表示链尾,然后对于不同块之间的合并就是直接把两条链对接,也就是一个的尾巴接到另一个的头上,构成新链(由于是链的直接叠加,所以可以做到严格的O(1),并且输出时输出多少复杂度就是多少,完全不存在额外复杂度).然后同时用原本的普通数组并查集进行维护和追踪(理论值为

【数据结构与算法】并查集基础

1.介绍 并查集是一种树型数据结构,用于处理一些不相交集合的合并问题. 并查集主要操作有: (1)合并两个不相交集合: (2)判断两个元素是否属于同一个集合: (3)路径压缩: 2.常用操作 用father[i]表示元素i的父亲结点,例如: 用某个元素所在树的根节点表示该元素所在集合: 判断两个元素是否属于同一个集合的时候,只需要判断他们所在树的根节点是否一样即可: 也就是说,当我们合并两个集合的时候,只需要在两个根节点之间连边即可. 获取根节点代码: 1 int findFather(int

算法:并查集

并查集是一种用途广泛的数据结构,能够快速地处理集合的合并和查询问题,并且实现起来非常方便,在很多场合中都有着非常巧妙的应用,.本文首先介绍并查集的定义.原理及具体实现,然后以其在最小生成树算法中的一个经典应用为例讲解其具体使用方法. 一 并查集原理及实现 并查集是一种树型的数据结构,用于处理一些不相交集合的合并及查询问题. 并查集在使用中通常以森林来表示,每个集合组织为一棵树,并且以树根节点为代表元素.实际中以一个数组father[x]即可实现,表示节点x的父亲节点.另外用一个变量n表示节点的个

(算法)并查集及其应用

题目: 某国家有N个小岛组成,经过多年的基础设施累积,若该岛屿之间建立若干桥梁,先重新完善该国的行政区划,规定只要有桥梁连接的岛屿则归属于同一个城市(可以通过其他岛屿中转),问该国可以划分为多少个城市? 思路: 并查集 代码: #include<iostream> #include<set> using namespace std; class UnionFindSet{ private: int m_nN; int* m_pParent; public: UnionFindSet

编程算法 - 食物链 并查集 代码(C)

食物链 并查集 代码(C) 本文地址: http://blog.csdn.net/caroline_wendy 题目: 有N仅仅动物, 分别编号为1,2,...,N. 全部动物都属于A,B,C中的一种. 已知A吃B, B吃C, C吃A. 按顺序给出两种信息K条. 第一种: x和y属于同一类. 另外一种: x吃y.  信息之间可能会出错和矛盾, 求不对的信息数. 比如: 有N=10仅仅动物, 给定K=7条信息. (1) 1: x=101, y=1; 出错:没有101的动物. (2) 2: x=1,

算法学习 并查集(笔试题目:找同伙)

题目背景太长,记得不清楚,暂参考<啊哈算法>一书,根据笔试题目大意改编如下: 警察正要捉获某地区的犯罪团伙,由于强盗人数过大,想查清楚有几个团伙非常困难. 根据上级指示,需要首先尽快抓获强盗A所在的团伙,这需要掌握 1 所在团伙的人数.先有资料如下: 强盗1 和 强盗2 是同伙 强盗3 和 强盗4 是同伙 强盗2 和 强盗5 是同伙 强盗3 和 强盗2 是同伙 注意,强盗的同伙的同伙也是同伙,问  强盗1 的同伙(不包括1自己)有多少人? 该题形式化表示如下: 每个测试实例首先包括2个整数:N

算法模板——并查集

实现功能——操作1:将两个数字合并到一个集合内:操作2:判断两个数字是否在一起 第6行是亮点,这个优化能快出不少,真的 1 var 2 i,j,k,l,m,n:longint; 3 c:array[0..100000] of longint; 4 function getfat(x:longint):longint;inline; 5 begin 6 if c[x]<>x then c[x]:=getfat(c[x]); //亮点在这里么么哒 7 exit(c[x]); 8 end; 9 be

【LCA】Tarjan离线算法(并查集+dfs)模板

vector <int> Q[N]; int Find(int x) { if(x != fa[x]) return fa[x] = Find(fa[x]); return x; } void Union(int x, int y) { int fx = Find(x), fy = Find(y); if(fy != fx) fa[fy] = fx; } void dfs(int u) { anc[u] = u; for(int i = head[u]; ~i; i = e[i].next)

3.19 Tarjan算法与并查集解决二叉树节点间最近公共祖先的批量查询问题

[题目]: 如下的Node类是标准的二叉树节点结构: 1 public class Node{ 2 public int value; 3 public Node left; 4 public Node right; 5 6 public Node(int data){ 7 this.value = data; 8 } 9 } 再定义Query类如下: 1 public class Query{ 2 public Node o1; 3 public Node o2; 4 5 public Que