并查集理解(1)



在某个城市里住着n个人,任何两个认识的人不是朋友就是敌人,而且满足:
我朋友的朋友是我的朋友;
我敌人的敌人是我的敌人;
已知关于 n个人的m条信息(即某2个人是朋友或者敌人),假设所有是朋友的人一定属于同一个团伙,请计算该城市最多有多少团伙?


我们考虑如何实现?【ps:关系逐个录入的】

Thinking~~分析一下

1.一开始集合是逐个自成一派的,假设有n个人,就有n个组
2.录入发现是朋友,就要合并,例如a与b 形成新的集合包含a与b的每个元素
3.重复1.2操作,直到关系录入完成

引入并查集解决


英文:Disjoint Set,即“不相交集合”
将编号分别为1…N的N个对象划分为不相交集合,
在每个集合中,选择其中某个元素代表所在集合。



常见两种操作:
1.合并两个集合union   2.查找某元素属于哪个集合find


方法1:
           用编号最小的元素标记所在集合;
           定义一个数组 set[1..n] ,其中set[i] 表示元素i 所在的集合;

          gg







     
public class Disjoint_Set1 {
	
    public static int find (int i,int []array)
    {
    	return array[i];
    }
    
    public static void union(int i,int j,int []array)
    {
    	int min,max;
    	if(i
     
     

时间复杂度分析:          这是一种最简单的实现,find是o(1),union是o(n)


再优化


find是不能优化了,union可以,我们把属于同一个集合的数字,组合成一个链表,这样可以快点
例如:
1-3-7  2-5-9-10各自是一个链表  此时来一个关系,3-2

我们选择把表长短的遍历一遍修改它的标记 ,这种实现朋友可以自己实现,事实上还有更好的方法,后面会介绍。







  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值