zoukankan      html  css  js  c++  java
  • 并查集与最小生成树

    并查集可以提供找两部分有没有通路的问题

    官方解释:并查集是一种树型的数据结构,用于处理一些不交集(Disjoint Sets)的合并及查询问题

    主要思路:

    建立一个数组记录每个数的父亲,初始的时候把每个人的父亲都设为他们自己

    之后如果两个数有关系,就把其中一个数的父亲修改为另一个数

    最后查询的时候只要递归查询父亲,找到最后的那个父亲,看看是否一样

    并查集模板

    https://www.luogu.com.cn/problem/P3367

     1 #include <iostream>
     2 #include<cstring>
     3 using namespace std;
     4 int pre[1000000], height[1000000];
     5 int find(int x)//递归查询父亲的操作
     6 {
     7     if (x != pre[x]) pre[x] = find(pre[x]);//如果他的父亲不是他自己,说明递归并没有到尽头
     8     return pre[x];
     9 }
    10 void uni(int b, int c)
    11 {
    12     int d = find(b);
    13     int v = find(c);
    14     if (height[d] == height[v])//如果高度一样,就默认选把右侧并到左侧
    15     {
    16         height[d] = height[d] + 1;
    17         pre[v] = d;
    18     }
    19     else
    20     {
    21         if (height[d] < height[v])//谁小就把谁并到大的里面
    22         {
    23             pre[d] = v;
    24         }
    25         else pre[v] = d;
    26     }
    27 }
    28 int main()
    29 {
    30     ios::sync_with_stdio(false);
    31     cin.tie(0);
    32     cout.tie(0);
    33     int n, m;
    34     cin >> n >> m;
    35     for (int i = 1; i <= n; i++) {//初始化
    36         pre[i] = i;
    37         height[i] = 0;
    38     }
    39     for (int i = 0; i < m; i++)
    40     {
    41         int a, b, c;
    42         cin >> a >> b >> c;
    43         if (a == 1)
    44         {
    45             uni(b, c);
    46         }
    47         if (a == 2)
    48         {
    49             int d = find(b);
    50             int v = find(c);
    51             if (d == v)cout << "Y" << endl;
    52             else cout << "N" << endl;
    53         }
    54     }
    55 }

    -------------------------------------------------------------------------------------------------------------------------

    团队题目:洛谷P1551亲戚

    https://www.luogu.com.cn/problem/P1551

     1 #include <iostream>
     2 #include<cstring>
     3 using namespace std;
     4 int pre[1000000], height[1000000];
     5 int find(int x)
     6 {
     7     if (x != pre[x]) pre[x] = find(pre[x]);
     8     return pre[x];
     9 }
    10 void uni(int b, int c)
    11 {
    12     int d = find(b);
    13     int v = find(c);
    14     if (d == v) return;
    15     if (height[d] == height[v])
    16     {
    17         height[d] = height[d] + 1;
    18         pre[v] = d;
    19     }
    20     else
    21     {
    22         if (height[d] < height[v])
    23         {
    24             pre[d] = v;
    25         }
    26         else pre[v] = d;
    27     }
    28 }
    29 int main()
    30 {
    31     ios::sync_with_stdio(false);
    32     cin.tie(0);
    33     cout.tie(0);
    34     int n, m, p;
    35     cin >> n >> m >> p;
    36     for (int i = 1; i <= n; i++) {
    37         pre[i] = i;
    38         height[i] = 0;
    39     }
    40     for (int i = 0; i < m; i++)
    41     {
    42         int a, b;
    43         cin >> a >> b;
    44         uni(a, b);
    45     }
    46     for (int i = 0; i < p; i++)
    47     {
    48         int c, d;
    49         cin >> c >> d;
    50         int mm = find(c);
    51         int nn = find(d);
    52         if (mm == nn)cout << "Yes" << endl;
    53         else cout << "No" << endl;
    54     }
    55     return 0;
    56 }

    -------------------------------------------------------------------------------------------------------------------------

    最小生成树

    https://www.luogu.com.cn/problem/P3366

    一个struct要记录左点,右点,长度(权值)三个信息

    输入完根据长度从小到大排列

    每次先处理最小的,把左点和右点用并查集合并,表示他们已经有关联

    如果左点和右点已经有同一个祖父亲,就说明他们已经相连了,就不需要再处理

     1 #include <iostream>
     2 #include <algorithm>
     3 using namespace std;
     4 int pre[300000], height[300000];
     5 struct line
     6 {
     7     int a, b, v;
     8 };
     9 line li[300000];
    10 bool cmp(line x, line y)
    11 {
    12     return x.v < y.v;
    13 }
    14 int find(int a)
    15 {
    16     if (a != pre[a]) pre[a] = find(pre[a]);
    17     return pre[a];
    18 }
    19 void uni(int a, int b)
    20 {
    21     int x = find(a);
    22     int y = find(b);
    23     if (height[x] == height[y])
    24     {
    25         height[x]++;
    26         pre[y] = x;
    27     }
    28     if (height[x] < height[y])
    29     {
    30         pre[x] = y;
    31     }
    32     else pre[y] = x;
    33 }
    34 int main()
    35 {
    36     ios::sync_with_stdio(false);
    37     cin.tie(0);
    38     cout.tie(0);
    39     int n, m;
    40     cin >> n >> m;
    41     for (int i = 1; i <= n; i++)
    42     {
    43         pre[i] = i;
    44         height[i] = 0;
    45     }
    46     for (int i = 0; i <m; i++)
    47     {
    48         cin >> li[i].a >> li[i].b >> li[i].v;
    49     }
    50     sort(li, li + m, cmp);
    51     int sum = 0;
    52     for (int i = 0; i < m; i++)
    53     {
    54         int x = find(li[i].a);
    55         int y = find(li[i].b);
    56         if (x != y) {
    57             uni(x, y); 
    58             sum += li[i].v;
    59         }
    60     }
    61     cout << sum << endl;
    62     return 0;
    63 }

    团队教学视频 @AE酱 (感谢大犇讲解)

    https://www.bilibili.com/video/BV1Pi4y1b7jZ

  • 相关阅读:
    Base64编码原理分析
    对 js 高程 Preflighted Reqeusts 的理解
    js 跨域 之 修改服务器配置-XAMPP-Apache (nginx 拉到最后!)
    js 模拟 select 的 click 事件
    串讲-解释篇:作用域,作用域链,执行环境,变量对象,活动对象,闭包
    js 匿名函数-立即调用的函数表达式
    Java I/O流输入输出,序列化,NIO,NIO.2
    Java8Lambda表达式
    设计模式之适配器模式
    设计模式之装饰器设计模式
  • 原文地址:https://www.cnblogs.com/Knightero/p/12878488.html
Copyright © 2011-2022 走看看