并查集 压缩路径

int find(int x)
{
    int k, j, r;
    r = x;
    while(r != parent[r])     //查找跟节点
        r = parent[r];      //找到跟节点,用r记录下
    k = x;
    while(k != r)             //非递归路径压缩操作
    {
        j = parent[k];         //用j暂存parent[k]的父节点
        parent[k] = r;        //parent[x]指向跟节点
        k = j;                    //k移到父节点
    }
    return r;         //返回根节点的值
}
void combine(int a,int b){  int t1=find(a);  int t2=find(b);  if(t1!=t2)    parent[t1]=t2;} 
时间: 2024-11-10 07:14:16

并查集 压缩路径的相关文章

并查集压缩路径

普通的并查集是这样婶的 void find1(int x) { int t=x; while(pre[t]!=t) { t=pre[t]; } } 如果复杂度比较高的话可以使用路径压缩(非递归版好理解,且不易爆栈),是这样婶的 void find1(int x) { int t=x; while(pre[t]!=t) { t=pre[t];//此时t就是最终的祖先 } int k=x;//k是最开始的那个点 while(t!=k) { int m=pre[k];//先保存一下结点的直接祖先: p

最小生成树个数 并查集压缩路径

1016: [JSOI2008]最小生成树计数 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 5843  Solved: 2379[Submit][Status][Discuss] Description 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的 最小生成树.(如果两颗最小生成树中至少有一条边不同,则这两个最小生成树就是不同的).由于不同的最小生 成树可能很多,所以你只需要输出方案数对3101

并查集的 路径压缩(递归和非递归)

这里的思路是 在每一次的找父亲节点的时候我们把每一个孩子的父亲的改成他的祖先.因为有可能一个孩子的关系很复杂可能就是一条链,这样查找就没浪费时间. //这是简单的递归实现 find (int x) { while(x!=father[x]) father[x] = find(father[x]) ; return father[x] ; } //这是非递归的 find (int x) { int r = x ; while(r != father[r])//找到r的祖先节点 r = father

poj1703Find them, Catch them(并查集以及路径压缩)

1 /* 2 题目大意:有两个不同的黑帮,开始的时候不清楚每个人是属于哪个的! 3 执行两个操作 4 A a, b回答a, b两个人是否在同一帮派,或者不确定 5 D a, b表示a, b两个人不在同一个帮派 6 7 思路:利用并查集将相同帮派的人合并到一起! 8 a ,b 不在同一个城市,那么 a, 和mark[b]就在同一个城市, 9 b 和 mark[a]就在同一个城市! 10 */ 11 #include<iostream> 12 #include<cstring> 13

hdu 1856 并查集(路径压缩)

hdu 1856 More is better 简单的并查集,用到了路径压缩 题意:找出节点数最多的连通分支,并输出该节点数. 思路:统计每个连通分支的节点数(利用并查集构建图时进行路径压缩,用一个与根节点下标对应的sum数组记录节点数),比较后得出最大值. 1 #include<cstdio> 2 #include<cstring> 3 4 int set[10000000 + 50]; 5 int sum[10000000 + 50]; 6 bool visit[1000000

[HDOJ2818]Building Block(带权并查集,路径压缩)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2818 题意:有N个块,每次有两个操作: M x y表示把x所在的那一堆全部移到y所在的那一堆的下方. C x 询问在x下方有多少个方块. 用并查集,在路径压缩的时候后序更新当前块下有多少个其他块,注意这里“当前块下”其实和并查集是相反的,也就是父亲节点在儿子下面. 需要额外维护一个量:某一堆的块的总数,这个在unite操作的时候,如果不是同一个根,直接将一部分加到另一部分上就可以. 1 /* 2 ━

[HDOJ3635]Dragon Balls(并查集,路径压缩)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3635 题意:有n个龙珠,n个城市.初始状态第i个龙珠在第i个城市里.接下来有两个操作: T A B:把A号龙珠所在的城市的所有龙珠全部转移到B城市中. Q A:查询A龙珠,要求:A龙珠所在城市,该城市龙珠数量,A移动的次数. 思路:用并查集可以轻松解决Q的前两个问题.关键在于如何统计A的移动次数,因为在T的时候是要将A所在城市的所有龙珠都要转移到B,那就要A集合里所有龙珠的移动次数都+1.假如我们在

poj1456Supermarket——并查集压缩查找

题目:http://poj.org/problem?id=1456 排序+贪心,每次选利润最大的,放在可能的最靠后的日期卖出,利用并查集快速找到下一个符合的日期. 代码如下: #include<iostream> #include<cstdio> #include<cstring> using namespace std; int n,t,ans,fa[10005]; struct N{ int p,d; }a[10005],hp[10005]; int find(in

并查集压缩hdu2818

#include<cstdio> #include<algorithm> using namespace std; int root[30010]; int num1[30010]; int num2[30010]; int find2(int x) { if(x != root[x]) { int fx = root[x]; root[x] = find2(fx); num1[x] += num1[fx]; } return root[x]; } void Union(int a