一、什么是并查集

在计算机科学中,并查集是一种树型的数据结构,用于处理一些不交集的合并及查询问题。有一个联合-查找算法(union-find algorithm)定义了两个用于次数据结构的操作:

  • Find:确定元素属于哪一个子集。它可以被用来确定两个元素是否属于同一子集。
  • Union:将两个子集合并成一个集合。

二、主要操作

  • 初始化:把每个点所在的集合初始化为其自身。
for(int i=1;i<=n;i++)
f[i]=i;
  • 查找:查找元素所在的集合,即根节点。
int find(int x)
{
while(f[x]!=x)
x=f[x];
return x;
}
  • 合并:将两个元素所在的集合合并为一个集合。
void Union(int x1,int x2)
{
int t1=find(x1);
int t2=find(x2);
if(t1!=t2)
f[t2]=t1;
}

三、优化

上面的代码看似简洁,但是每一次find操作的时间复杂度为O(H),H为树的高度,由于我们没有对树做特殊处理,所以树的不断合并可能会使树严重不平衡,最坏情况每个节点都只有一个子节点。

所以在find函数里采用路径压缩

int find(int x)       //查找x元素所在的集合,回溯时压缩路径
{
if (x != f[x])
{
f[x] = find(f[x]);
//从x结点搜索到祖先结点所经过的结点都指向该祖先结点
}
return f[x];
}

四、模板题

洛谷P3367【模板】并查集

#include<bits/stdc++.h>
using namespace std;
int n,m;
int f[10002];
int find(int x)
{
if(x!=f[x])
f[x]=find(f[x]);
return f[x];
}
void Union(int x1,int x2)
{
int t1=find(x1);
int t2=find(x2);
if(t1!=t2) //祖先不一样
f[t2]=t1; //把t2的祖先变为x1的祖先t1
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
f[i]=i;
for(int i=0;i<m;i++)
{
int z,x,y;
cin>>z>>x>>y;
if(z==1)
Union(x,y);
else
{
if(find(x)!=find(y))cout<<"N"<<endl;
else cout<<"Y"<<endl;
}
}
return 0;
}

五、最小生成树

一个有n个结点的连通图的生成树是原图的极小联通子图,期包含原图的所有n个结点,且有保持图连通的最少边。

最小生成树其实就是最小权重生成树的简称。

Kruskal算法

  • 将图的所有边按照权值从小到大排序
  • 遍历所有排好序的边,若构不成回路,则将该边加入到集合中
  • 直到找出n-1条边

例题:繁忙的都市

#include<bits/stdc++.h>
using namespace std;
int n,m;
int s,maxm;
int p[100002];
struct node{
int u;
int v;
int c;
}info[100002]; bool cmp(node x1,node x2)
{
if(x1.c!=x2.c)return x1.c<x2.c;
else if(x1.u!=x2.u) return x1.u<x2.u;
else return x1.v<x2.v;
}
int find(int x) //查找x元素所在的集合,回溯时压缩路径
{
if (x!=p[x])
{
p[x]=find(p[x]);
}
return p[x];
}
void bcj(int x1,int x2)//把x2并入x1的集合
{
int t1,t2;//存储祖先节点
t1=find(x1);
t2=find(x2);
if(t1!=t2)p[t2]=t1;
}
int main()
{
cin>>n>>m;//n就是顶点数,m是边数
for(int i=1;i<=n;i++)
{
p[i]=i;
}
for(int i=0;i<m;i++)
{
cin>>info[i].u>>info[i].v>>info[i].c;
}
sort(info,info+m,cmp);
for(int i=0;i<m;i++)//遍历所有的边
{
if(find(info[i].u)!=find(info[i].v))
{
bcj(info[i].u,info[i].v);//把v并入u的集合
maxm=max(maxm,info[i].c);
}
}
cout<<n-1<<" "<<maxm;
return 0;
}

并查集与最小生成树Kruskal算法的更多相关文章

  1. hdu 1233(还是畅通project)(prime算法,克鲁斯卡尔算法)(并查集,最小生成树)

    还是畅通project Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Tota ...

  2. POJ-2421Constructing Roads,又是最小生成树,和第八届河南省赛的引水工程惊人的相似,并查集与最小生成树的灵活与能用,水过~~~

    Constructing Roads Time Limit: 2000MS   Memory Limit: 65536K               Description There are N v ...

  3. 【转】最小生成树——Kruskal算法

    [转]最小生成树--Kruskal算法 标签(空格分隔): 算法 本文是转载,原文在最小生成树-Prim算法和Kruskal算法,因为复试的时候只用到Kruskal算法即可,故这里不再涉及Prim算法 ...

  4. 模板——最小生成树kruskal算法+并查集数据结构

    并查集:找祖先并更新,注意路径压缩,不然会时间复杂度巨大导致出错/超时 合并:(我的祖先是的你的祖先的父亲) 找父亲:(初始化祖先是自己的,自己就是祖先) 查询:(我们是不是同一祖先) 路径压缩:(每 ...

  5. POJ 3723 Conscription (Kruskal并查集求最小生成树)

    Conscription Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 14661   Accepted: 5102 Des ...

  6. 关于最小生成树(并查集)prime和kruskal

    适合对并查集有一定理解的人.  新手可能看不懂吧.... 并查集简单点说就是将相关的2个数字联系起来 比如 房子                      1   2    3   4  5   6 ...

  7. 【Matrix-tree定理】【并查集】【kruscal算法】bzoj1016 [JSOI2008]最小生成树计数

    题意:求一个图的最小生成树个数. 矩阵树定理:一张无向图的生成树个数 = (度数矩阵 - 邻接矩阵)的任意一个n-1主子式的值. 度数矩阵除了对角线上D[i][i]为i的度数(不计自环)外,其他位置是 ...

  8. 最小生成树——kruskal算法

    kruskal和prim都是解决最小生成树问题,都是选取最小边,但kruskal是通过对所有边按从小到大的顺序排过一次序之后,配合并查集实现的.我们取出一条边,判断如果它的始点和终点属于同一棵树,那么 ...

  9. 最小生成树 kruskal算法&prim算法

    (先更新到这,后面有时间再补,嘤嘤嘤) 今天给大家简单的讲一下最小生成树的问题吧!(ps:本人目前还比较菜,所以最小生成树最后的结果只能输出最小的权值,不能打印最小生成树的路径) 本Tianc在刚学的 ...

随机推荐

  1. MySQL 事务 MVCC 版本链

      版本链   对于使用InnoDB存储引擎的表来说,它的聚簇索引记录中都包含两个必要的隐藏列(row_id并不是必要的,我们创建的表中有主键或者非NULL唯一键时都不会包含row_id列):  1) ...

  2. bzoj 1415: [Noi2005]聪聪和可可 期望dp+记忆化搜索

    期望dp水题~ 你发现每一次肯定是贪心走 2 步,(只走一步的话就可能出现环) 然后令 $f[i][j]$ 表示聪在 $i$,可在 $j$,且聪先手两个人碰上面的期望最小次数. 用记忆化搜索转移就行了 ...

  3. Codeforces Round #574 (Div. 2)

    目录 Contest Info Solutions A. Drinks Choosing B. Sport Mafia C. Basketball Exercise D1. Submarine in ...

  4. 均匀量化(lena图)

    #include<stdio.h> #include<math.h> #define ROW 512 #define COL 512 typedef unsigned char ...

  5. CSPS2019游(tuifei)记

    %%%脸哥没脸%%% Day0,日常考前紧张,做不下题去.听各大主任送祝福(从里红(wa)到外) 然后就出发了,大巴上和云力一起坐,吃了好多东西.中午因不满火车站的不合理收费,选择了面包+火腿 下午在 ...

  6. Matlab学习——求解微分方程(组)

    介绍: 1.在 Matlab 中,用大写字母 D 表示导数,Dy 表示 y 关于自变量的一阶导数,D2y 表示 y 关于自变量的二阶导数,依此类推.函数 dsolve 用来解决常微分方程(组)的求解问 ...

  7. codeforces396C

    On Changing Tree CodeForces - 396C You are given a rooted tree consisting of n vertices numbered fro ...

  8. hive on tez 错误记录

    1.执行过程失败,报 Container killed on request. Exit code is 143 如下图: 分析:造成这种原因是由于总内存不多,而容器在jvm中占比过高,修改tez-s ...

  9. 免sudo使用docker

    前沿:通过root安装完docker,在普通用户下执行docker相关命令的时候,报权限不足: 查看sock文件的权限: [hadoop@slave1 monitor]$ ll /var/run/do ...

  10. Arts打卡第8周

    Algorithm.主要是为了编程训练和学习. 每周至少做一个 leetcode 的算法题(先从Easy开始,然后再Medium,最后才Hard). 进行编程训练,如果不训练你看再多的算法书,你依然不 ...