并查集——新手学习记录

好吧,什么垃圾并查集,并查集什么的都是铁憨憨<+__+>

现在开始复习回忆:(新手,有错误望指正)

什么叫做并查集,并查集就是一个集合问题,其实最主要的就是知道并查集是一个求解集合数目的问题,具体的操作方法有点飘。

或者这样理解:——并查集通过一个一维数组来实现,其本质是维护一个森林。(好吧,我也不是很理解),我的理解就是通过一维数组来实现,子节点与父节点之间联系,然后查找集合个数。。。。。。。

好吧,不清楚,如果看了前面你很懵逼,那就全都忘了吧,,,

接下来才是正餐:https://blog.51cto.com/ahalei/2348145

直接上代码:

题目是杭电的畅通工程:http://acm.hdu.edu.cn/showproblem.php?pid=1232

#include<stdio.h>
int fa[1001]={0};
void zore(int n)//未知量用n表示,初始化
{
    for(int i=1;i<=n;i++)
        fa[i]=i;
}

int find_father(int x)//返回老大,或者说是根节点
{
    if(fa[x]== x)
        return x;
    else{
        fa[x]=find_father(fa[x]);//优化路径
        return fa[x];
    }
}

void unions(int n,int m)
{
    if(find_father(n)!=find_father(m))
        fa[find_father(m)]=find_father(n);
}

int main()
{
    int n,m;
    while(scanf("%d %d",&n,&m)&&n)
    {
        int sum=0;
        zore(n);
        while(m--)
        {
            int a,b;
            scanf("%d %d",&a,&b);
            unions(a,b);
        }
        for(int i=1;i<=n;i++)
        {
            if(fa[i]==i)
                sum++;
        }
        printf("%d\n",sum-1);
    }
    return 0;
}

现在我们把代码拆开来说:

int main()
{
    int n,m;//题目中的n代表城市个数,m代表道路数
    while(scanf("%d %d",&n,&m)&&n)
    {
        int sum=0;//用来预装需要修的路数
        zore(n);//调用初始化函数,来使我们的一维数组初始化
        while(m--)//输入m条路
        {
            int a,b;//a,b分别代表道路的起始城市的标号
            scanf("%d %d",&a,&b);
            unions(a,b);//合并有相邻道路的城市,为最后计算道路数做准备:比如最后如果只有两个集合,只需要修一条路;三个集合两条路的思想。
        }
        for(int i=1;i<=n;i++)
        {
            if(fa[i]==i)//寻找到底有几个独立集合                sum++;
        }
        printf("%d\n",sum-1);
    }
    return 0;
} 

接下来:

int fa[1001]={0};
void zore(int n)//初始化作用,这点很重要,因为这个操作为我们接下来的操作提供了数据
{
    for(int i=1;i<=n;i++)
        fa[i]=i;
}

 再接下来:

int find_father(int x)//这个very very重要
{  //作用是查找根结点,父节点...>如果你看过第一篇文章,你就把他理解成最大的BOOS就好了
    if(fa[x]== x)如果查找点自己就是自己的最大BOOS,则返回
        return x;
    else{
        fa[x]=find_father(fa[x]);//优化路径,其实 是一个递归调用
        return fa[x];//优化过后改变了树的结构,  子节点很多直接变成了根结点
    }
}

  再接下来再:

void unions(int n,int m)
{
    if(find_father(n)!=find_father(m))//合并操作..>其实就是当两个人的老大不一个人的时候,然而却需要建立联系,好吧,这个时候两个人就要开始干架了,最直接的方法是       fa[find_father(m)]=find_father(n);//直接让两个人的老大来谈话,让一个老大认另一个人的老大为老大,此时他们就属于同一个集合,此时就消除了集合间的隔离,或者说                                         //合并了两个集合

}

 

void unions(int x,int y)
{
    int b1=find_father(n);//或者变成这样,x市到y市之间有一条路,查询x与y市的老大是谁
    int b2=find_father(m);
    if(b1!=b2)//判断x与y市在不在一个集合
        fa[b1]=b2;//如果不在,合并
}

原文地址:https://www.cnblogs.com/ZZ34/p/10759760.html

时间: 2024-10-12 02:29:22

并查集——新手学习记录的相关文章

selenium 学习笔记 ---新手学习记录(1) 问题总结

说明:每次学习各种语言时,环境搭建访问国外网址最头疼了,现在只要是工具下载好放到自己网盘,可以随时用. 1.首先工具准备,selenium需要用到的 下载地址 访问密码 ff8f 2.我选择的语言时junit eclipse开发 junit包下载: 下载 访问密码 c23d eclipse自己百度 3.实例练习. 具体步骤百度 4.遇见的问题 等待解决的 1).如下图,如何让变量pwds每次自动加1呢?假设pwds初始值为1,我想每次自动加1,向下图所示在我运行完${pwds}+1后我打印出来结

并查集知识学习

(转) 并查集的作用:并和查,即合并和查找,将一些集合合并,快速查找或判断某两个集合的关系,或某元素与集合的关系,或某两个元素的关系. 并查集的结构:并查集主要操作对象是森林,树的结构赋予它独特的能力,对整个集合操作转换为对根节点(或称该集合的代表元素)的操作,一个集合里的元素关系不一定确定,但相对于根节点的关系很明了,这也是为了查找方便. 并查集优化方法:按秩合并和路径压缩的配合使用,使得查找过程优化到极致.按秩合并,每次将深度小的树合并到深度大的树里面去,使得整棵树尽量矮:路径压缩,将当前节

HBase混布MapReduce集群学习记录

一.准备工作 1.1 部署环境 集群规模大概260多台,TSC10机型,机型参数如下: > 1个8核CPU(E5-2620v4) > 64G内存 > HBA,12*4T SATA,1*240G SSD, > 2*10G网口 1.2 机器分配 HBase和Hadoop的主结点共用,子结点也共用. 角色 机型 数量 HBase Master&Hadoop Namenode B6 2 HBase RegionServer&Hadoop Datanode TSC10 265

jmeter cookie管理器 使用方法---新手学习记录1

首先得抓包: 我已post方法为例: POST /api/datasources/lemontest/jaql HTTP/1.1 Host: 192.168.1.107:8081 Content-Length: 916 Accept: application/json, text/plain, */* Origin: http://192.168.1.107:8081 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.

selenium 学习笔记 ---新手学习记录(2) 问题总结

今天研究了下ie.chrome.firefox浏览器执行脚本 1.首先firefox下执行时,我是安装在d盘了,所以要更改路径 //如果火狐浏览器没有默认安装在C盘,需要制定其路径 System.setProperty("webdriver.firefox.bin", "D:/Softwareinstallation/huohu/firefox.exe");  WebDriver driver = new FirefoxDriver(); 2.在chrome下执行时

selenium 学习笔记 ---新手学习记录(7) 问题总结(java)

1.想要获取固定ul下所有li的个数  如下图: //获取ul下li的个数 List<WebElement> elements = driver.findElement(By.id("firstulid")).findElements(By.tagName("li")); System.out.println("size:"+elements.size());

poj1417(种类并查集+dp)

题目:http://poj.org/problem?id=1417 题意:输入三个数m, p, q 分别表示接下来的输入行数,天使数目,恶魔数目: 接下来m行输入形如x, y, ch,ch为yes表示x说y是天使,ch为no表示x说y不是天使(x, y为天使,恶魔的编号,1<=x,y<=p+q):天使只说真话,恶魔只说假话: 如果不能确定所有天使的编号,输出no,若能确定,输出所有天使的编号,并且以end结尾: 注意:可能会有连续两行一样的输入:还有,若x==y,x为天使: 思路:种类并查集+

hdu 1558 线段相交+并查集路径压缩

Segment set Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3457    Accepted Submission(s): 1290 Problem Description A segment and all segments which are connected with it compose a segment set.

HDU1811 并查集+拓扑排序

题目大意: 判断是否能根据给定的规则将这一串数字准确排序出来 我们用小的数指向大的数 对于相等的情况下,将二者合并到同一个并查集中,最后抽象出来的图上面的每一个点都应该代表并查集的标号 1 #include <cstdio> 2 #include <cstring> 3 #include <stack> 4 #include <iostream> 5 using namespace std; 6 7 #define N 10005 8 char s[N<