HDU/HDOJ 1232 超详细题解(并查集入门教程)
来源:互联网 发布:数据挖掘常用软件 编辑:程序博客网 时间:2024/05/18 00:53
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1232
HDU1232这道题属于并查集
思路:
城市之间由道路连接,相连的城市可以看做一个集合,如:a、b相连,c、d相连,则a和b属于集合A,c和d属于集合B。之后又有人告诉你b和e相连,那么就把e加入到集合A中,以此类推。然后不同集合若是想组成一个大的集合,即集合A和集合B若相连接在一起,那随便在两个集合中分别找两个城市连接在一起就可以了。
在这里稍微讲解一下并查集,并查集一般由一个整形数组和两个函数构成,其中数组pre[x]记录的是x的前导节点,若把并查集中的节点看做数的话,那pre[x]数组中记录的就是x的父节点。
大家都知道树有个根节点,我们把集合A和集合B分别看成两棵树,每棵树上的节点都可以互相连接,那任意给我两个节点我怎样才能分辨是否相连通呢?我们就可以判断他的根节点是什么,若根节点相同,说明两个节点都属于集合A(或集合B)并且可以连通。
所以可以通过find函数来寻找某节点的根节点:
int find (int x){int r;//r代表的是根节点while(pre[r]!=r){//根节点的pre存的是它自己r=pre[r];}return r;}
题目中给我们的是x,y两个城市的编号,告诉我们他们可以连接,那我们如何用代码来体现呢?
我们可以写一个join函数,用于把x,y加入到某个集合中去,证明他们能连通。
可以通过修改x或y根节点的前导数组pre来实现:
int join(int x,int y){int r_x=find(x),r_y=find(y);//寻找到x和y的根节点,判断x,y是否连通if(r_x!=r_y){//若两者的根节点相同就不用执行了//让x的根节点的前导改为y节点的根节点,相当于把x和y所在的树合并成一颗树。这样x,y在树中连通。pre[r_x]=r_y;//这里也可以写成pre[r_y]=r_x,只要把x,y的根节点改成一样就行了}}
优化:
大家想想还有没有什么优化方法?
当然是有的,若是经常判断某两个节点的根节点是什么,每次都要执行一次find里面的循环,有没有觉得很浪费?我们明明找一次根节点就行了。
看图:
这样的话找f的根节点的时候直接找pre[f]就行了,不用每次遍历一次,一次修改,终身受用。
所以find函数可以改成这样:
int find(int x){ int r=x; while(pre[r]!=r){ r=pre[r]; } //找到根节点r之后,把这棵树的所有节点的前导全部改为r这样就不用每次都上探寻找一次根节点了 int i=x,j;//j是个临时变量,存放i的前导 while(i!=r){//一直执行到根节点 j=pre[i]; pre[i]=r; i=j; }//把经过的节点的前导全改成r return r;}
这个方法专业点的叫法是——路径压缩。
还有个注意的地方,就是开始必须初始化所有的节点的前导都是自己,也就是pre[x]=x;
好了,分析过程都讲完了,贴个完整的代码:
#include <stdio.h>#include <stdlib.h>#include <string.h>int pre[1010];int find(int x){//查找并返回某个节点的根节点 int r=x;//根节点root while(pre[r]!=r){ r=pre[r]; } int i=x,j; while(i!=r){//路径压缩,让所有节点的pre直接指向根节点 j=pre[i]; pre[i]=r; i=j; } return r;}void join(int x,int y){ int r_x=find(x),r_y=find(y); if(r_x!=r_y){ pre[r_x]=pre[r_y]; }}int main(){ int hash[1010]; int n,m,i,x,y,sum;while(scanf("%d%d",&n,&m)&&n){ //初始化 sum=0; memset(hash,0,sizeof(hash)); for(i=1;i<=n;i++){ pre[i]=i; } while(m--){ scanf("%d%d",&x,&y); join(x,y); } for(i=1;i<=n;i++){ hash[find(i)]=1; } for(i=1;i<=n;i++){ sum+=hash[i]; } printf("%d\n",sum-1); } return 0;}
- HDU/HDOJ 1232 超详细题解(并查集入门教程)
- HDU 1272详细题解(并查集)
- 题解:HDU 1232: 畅通工程 (并查集)
- POJ 2524 Ubiquitous Religions 详细题解(并查集)
- hdu/hdoj 1232 畅通工程---并查集
- HDU/HDOJ 1181(并查集orDFS)
- HDOJ-1232(并查集)
- 并查集(题解)
- HDOJ-1232(并查集)
- HDOJ-----1232并查集
- hdoj 1232+hdoj 1272 (并查集)
- 并查集(union-find set)hdoj/hdu 1232畅通工程
- poj1182超详细的种类并查集
- 一篇超强超详细的并查集详解
- 超详细的并查集讲解 首发
- RecyclerView 入门教程(超详细)
- RecyclerView 入门教程(超详细)
- 并查集题解
- GIT(分布式管理工具)
- hive 中使用shell/python
- AKKA笔记
- 探索 OpenStack 之:计量模块 Ceilometer 介绍及优化
- 多模板layout
- HDU/HDOJ 1232 超详细题解(并查集入门教程)
- 数独100*100 sudoku 100*100 的第一个结果
- 数据库中的char类型的字段与number,varchar类型字段查询
- alibaba dexposed初步解析
- android webview 自定义404错误页面!
- Passing data between view controller.
- 欢迎使用CSDN-markdown编辑器
- 输入半径与高求圆周长、面积,圆球表面积、体积,圆柱表面积、体积
- manifest.xml属性笔记