本周学习了并查集,并查集我对他的理解是从底层向上寻找源头,就好比根据河流入海口,我们可以一步步找到它的发源地是哪里,但是,我们无法从源头向下寻找底层,就像无法从河流发源地去寻找入海口一样:
一·个人理解:
基础的并查集主要分为两种,一种是一般并查集,主要用来处理无权的相对关系,比如说A和B是一类人,B和C是一类人,那么A和C也是一类人。一般的并查集主要记录节点之间的链接关系,而没有其他的具体的信息,仅仅代表某个节点与其父节点之间存在联系,如下图所示,这是一个并查集,其中箭头表示父子关系,可以看到这些边没有记录其他的任何信息。
另一种是带权并查集,如上图所示,假如每条边都带有额外的信息,那就属于带权并查集,额外的信息需要用一个额外的数组去记录。(并查集储存的信息是某点属于哪个集合,而带权并查集还能记录某点和其父结点的“关系”)
并查集用于处理不相交集合的合并(join[])和查询(find[])问题,它会有几个基本的操作:
1.初始化:建立一个并查集,使得每个元指向自身
const int MX =100006 ;
struct node
{
int parent,relation ;
}T[MX] ;
void init(int n)
{
for(int i=1 ;i<=n ;i++)
{
T[i].parent=i ;
T[i].relation=0 ;// 表示此节点与根节点的关系,用于带权并查集,如果只是单纯的并查集这里可以省略
}
}
2.查找:find(x),查找x的祖先(这样可以判断两个元素是否在同一个集合中):
int find(int x)
{
return T[x].parent==x ? x : T[x].parent=find(T[x].parent) ;// 路径压缩
}
3.合并: 合并 x 与 y 所在的集合.
void uniteSet(int leaderX, int leaderY)//x和y是两个最高父类
{
leader[leaderX] = leaderY;
}
二·例题:
最大食物链计数:
https://www.luogu.com.cn/problem/P4017
题目描述
给你一个食物网,你要求出这个食物网中最大食物链的数量。
(这里的“最大食物链”,指的是生物学意义上的食物链,即最左端是不会捕食其他生物的生产者,最右端是不会被其他生物捕食的消费者。)
Delia 非常急,所以你只有 11 秒的时间。
由于这个结果可能过大,你只需要输出总数模上 8011200280112002 的结果。
输入格式
第一行,两个正整数 n、mn、m,表示生物种类 nn 和吃与被吃的关系数 mm。
接下来 mm 行,每行两个正整数,表示被吃的生物A和吃A的生物B。
输出格式
一行一个整数,为最大食物链数量模上 8011200280112002 的结果。
输入输出样例
输入 #1复制
5 7 1 2 1 3 2 3 3 5 2 5 4 5 3 4
输出 #1复制
5
说明/提示
各测试点满足以下约定:
我们将食物链中的生物看作是就一个个的节点,生物之间的关系则为有向边,由于数据不会出现环,所以最大食物链左端是不会捕食生物的路径,他的入度为零。右端是不会被其它生物捕食的路径,他的出度为零。
想要找到一条 最大食物链 ,那么这条路径的起点入度要为0,终点出度要为0。 故:
既要记录入度,还要记录出度!
现在的问题转换成了,如何找到图中所有 左端点入度为0 且 右端点出度为0 的路径的数量。
结果为到达红色点的路经总和。
第一轮:删除 1 号蓝色点,1 号蓝色点可以到的点(2号点、3 号点)都加 1
第二轮:删除 2 号点,2 号点可以到的点(3 号点、5 号红色点)都加 1。此时 3 号点答案为 2,5 号点答案为 1
第三轮:删除3 号点,3 号点可以到的点(4 号点、5 号红色点)都加 2。此时 5 号点答案为 3,4 号点答案为 2
第四轮:最后删除 4号点,4 号点可以到的点(5 号红色点)加 2,此时 5 号点答案为 5
可见全图只有 5 号一个红色点,那么答案就是 5号点的答案———— 5 了
总结:这两个周我感觉自己的学习状态不对,明显没有以前的干劲了,我个人感觉,一部分是因为我变得懈怠了,还有就是近期各种事情搞得我变得心浮气躁,这种状态急需改变!!