Title

数据结构——并查集

并查集

特点

根节点的父节点是自己

材料准备

fa[x]表示的是x的父节点。

操作

找到根节点

一般路径

  • 借用递归(根节点的父节点是自己
int find(int x)
{
      if(fa[x]==x)return x;
      else return find(fa[x]);
}
  • 缩行
int find(int x)
{
     return fa[x]==x?x:find(fa[x]);
}

路径压缩(实为合并)

int find(int x)
{
    if(fa[x]==x)
      return x;
    else{
         fa[x]= find(fa[x]);//如果有x有多辈祖宗,也会被搞成只剩一辈
         return fa[x];
    }
}
  • 缩行
int find(int x)
{
     return fa[x]==x?x:fa[x]=find(fa[x]);
}

合并

  • 令i的根节点的父节点变成j
void merge(int i,int j)
{
    fa[find(i)] = find(j);
}

P1111 修复公路

题目背景

AA地区在地震过后,连接所有村庄的公路都造成了损坏而无法通车。政府派人修复这些公路。

题目描述

给出A地区的村庄数NN,和公路数MM,公路是双向的。并告诉你每条公路的连着哪两个村庄,并告诉你什么时候能修完这条公路。问最早什么时候任意两个村庄能够通车,即最早什么时候任意两条村庄都存在至少一条修复完成的道路(可以由多条公路连成一条道路)

输入格式

第11行两个正整数N,MN,M

下面MM行,每行33个正整数x, y, tx,y,t,告诉你这条公路连着x,yx,y两个村庄,在时间t时能修复完成这条公路。

输出格式

如果全部公路修复完毕仍然存在两个村庄无法通车,则输出-1−1,否则输出最早什么时候任意两个村庄能够通车。

思路

  • 时间从小到大(排序,模拟)

  • 并查集(所有结点指向同一结点时结束)

    • 并查集初始化(所有点都指向自身)

    • 如果fx和fy的头节点不同的话

    • f[fx]=fyf[fy]=fx的差别

      • f[fx]=fy:fx的头节点是fy,且经过路径压缩后,fx的子节点都会归并到fy的名下。

      • f[fy]=fx:fy的头节点是fx,且经过路径压缩后,fy的子节点都会归并到fx的名下。

      • 所以两者的差别仅是合并后点的父节点的暂时不同。

  • 代码

 int find(int x){return f[x]==x?x:f[x]=find(f[x])}
  • f[x]=find(f[x])表示的是以x的父节点f[x]为根据找到最终的父节点,并将最终的父节点更新为原本的父节点。

  • 注意:每进行一次合并就是意味着孤立的点减少一。注意:合并的前提是这两个点最终的父节点是不同的。

参考

洛谷题解

知乎并查集

posted @ 2021-03-23 13:03  BeautifulWater  阅读(78)  评论(0编辑  收藏  举报