在某个城市里住着n个人,任何两个认识的人不是朋友就是敌人,而且满足:
我朋友的朋友是我的朋友;
我敌人的敌人是我的敌人;
已知关于 n个人的m条信息(即某2个人是朋友或者敌人),假设所有是朋友的人一定属于同一个团伙,请计算该城市最多有多少团伙?
我朋友的朋友是我的朋友;
我敌人的敌人是我的敌人;
已知关于 n个人的m条信息(即某2个人是朋友或者敌人),假设所有是朋友的人一定属于同一个团伙,请计算该城市最多有多少团伙?
我们考虑如何实现?【ps:关系逐个录入的】
Thinking~~分析一下
1.一开始集合是逐个自成一派的,假设有n个人,就有n个组
2.录入发现是朋友,就要合并,例如a与b 形成新的集合包含a与b的每个元素
3.重复1.2操作,直到关系录入完成
引入并查集解决
将编号分别为1…N的N个对象划分为不相交集合,
在每个集合中,选择其中某个元素代表所在集合。
常见两种操作:
1.合并两个集合union 2.查找某元素属于哪个集合find
1.合并两个集合union 2.查找某元素属于哪个集合find
方法1:
用编号最小的元素标记所在集合;
定义一个数组 set[1..n] ,其中set[i] 表示元素i 所在的集合;
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
我们选择把表长短的遍历一遍修改它的标记
,这种实现朋友可以自己实现,事实上还有更好的方法,后面会介绍。