数据结构(荣誉)实验一 并查集

简介: 数据结构(荣誉)实验一 并查集

1.并查集基础


题目描述


现在有一个并查集,你需要完成合并和查询操作。


输入


第一行包含两个整数 N,M ,表示共有 N 个元素和 M 个操作。

接下来M 行,每行包含三个整数 Zi,Xi,Yi 。

当 Zi=1 时,将 Xi 与 Yi 所在的集合合并。

当Zi=2 时,输出Xi 与 Yi 是否在同一集合内,是的输出 Y ;否则输出 N 。


输出


对于每一个Zi=2 的操作,都有一行输出,每行包含一个大写字母,为 Y 或者 N 。


样例输入


4 7

2 1 2

1 1 2

2 1 2

1 3 4

2 1 4

1 2 3

2 1 4


样例输出


N

Y

N

Y


题解

#include <iostream>
using namespace std;
int main() {
 int n, t;
 cin >> n >> t;
 int* arr = new int[n+10];
 for (int i = 0; i < n+1; i++) {
  arr[i] = i;
 }
 while (t--) {
  int a, b, c;
  cin >> a >> b >> c;
  if (a == 1) {
   while (arr[b]!=b) {
    b = arr[b];
   }
   while (arr[c] != c){
    c = arr[c];
   }
   arr[c] = b;
  }
  else if (a == 2) {
   while (arr[b] != b) {
    b = arr[b];
   }
   while (arr[c] != c) {
    c = arr[c];
   }
   if (arr[b] == arr[c]) {
    cout << "Y" << endl;
   }
   else {
    cout << "N" << endl;
   }
  }
 }
}


2. 红娘


题目描述


小明在A公司工作,小红在B公司工作。A公司有N名男员工,其中有P对有朋友关系。B公司有M名女员工,其中有Q对有朋友关系。假设朋友的朋友还是朋友。

每对朋友关系用两个整数(Xi, Yi)组成,表示朋友的编号分别为Xi,Yi。男人的编号是正数,女人的编号是负数。小明的编号是1,小红的编号是-1.

小明和小红是情侣,他们想撮合A、B公司的员工成为情侣。只有异性男女才能成为情侣,而且任何一方都不能脚踏两只船哦。那么,请问两公司之间,通过小明和小红认识的人最多一共能配成多少对情侣。(包括他们自己)


输入


第1行,4个空格隔开的正整数N,M,P,Q。

之后P行,每行两个正整数, Xi, Yi。

之后Q行,每行两个负整数, Xi, Yi。


输出


一个正整数,表示通过小明和小红认识的人最多一共能配成多少对情侣。(包括他们自己)


样例输入


4 3 4 2

1 1

1 2

2 3

1 3

-1 -2

-3 -3


样例输出


2


题解

#include <algorithm>
#include <iostream>
using namespace std;
class UnionSet
{
private:
    int *roots;
    int length;
public:
    UnionSet(int n)
    {
        roots = new int[n + 1];
        for (int i = 1; i <= n; i++)
        {
            roots[i] = i;
        }
        length = n;
    }
    ~UnionSet()
    {
        delete[] roots;
    }
    int find(int a)
    {
        int p = a;
        while (roots[p] != p)
        {
            p = roots[p];
        }
        return p;
    }
    void unionMerge(int a, int b)
    {
        int x = find(a);
        int y = find(b);
        roots[y] = x;
    }
    int countRoot()
    {
        int x = find(1);
        int num = 0;
        for (int i = 1; i <= length; i++)
        {
            if (x == find(i))
            {
                num++;
            }
        }
        return num;
    }
};
int main()
{
    int n, m, p, q;
    cin >> n >> m >> p >> q;
    UnionSet male(n);
    UnionSet female(n);
    while (p--)
    {
        int x, y;
        cin >> x >> y;
        male.unionMerge(x, y);
    }
    while (q--)
    {
        int x, y;
        cin >> x >> y;
        female.unionMerge(-x, -y);
    }
    cout << min(male.countRoot(), female.countRoot()) << endl;
    return 0;
}


3.滑雪


题目描述


David是个滑雪初学者,他还没有学会如何在滑行过程中控制方向,也不知道如何停下来。所以他的滑行方式只能是在一个高高的雪堆上调整好向北,东,南或西移动的方向,然后直线滑下来,一直滑倒另一个雪堆底下才能停下来。


他发觉以这种方式,有些雪堆他是无法到达的。因此,他现在想在已有的雪堆基础上,自己再人为地增加一些雪堆,使得他可以从任何雪堆转移到其他任何雪堆。他请求您帮他找到需要创建的雪堆的最少数量。


我们假设David只能在整数坐标处堆积雪堆。


9798a0b91d5042e1995783bd28dc437e.png


输入


输入的第一行包含一个整数n(1≤n≤100),表示已有的雪堆数量。 接下来的n行中的每行包含两个整数Xi和Yi(1≤Xi,Yi≤1000),表示已有的第i个雪堆的坐标。

请注意,北方向与Oy轴方向一致,因此东方向与Ox轴方向一致。 所有雪堆的位置都不同。


输出


输出为使David能够从任何雪堆到达其他任何雪堆而需要创建的最小雪堆数。


样例输入


2

2 1

1 2


样例输出


1


题解

#include <algorithm>
#include <iostream>
#include <set>
using namespace std;
class UnionSet
{
private:
    int *roots;
    int length;
public:
    UnionSet(int n)
    {
        roots = new int[n + 1];
        for (int i = 1; i <= n; i++)
        {
            roots[i] = i;
        }
        length = n;
    }
    ~UnionSet()
    {
        delete[] roots;
    }
    int find(int a)
    {
        if(roots[a] == a)
        {
            return a;
        }else
        {
            return find(roots[a]);
        }
    }
    void merge(int a, int b)
    {
        int x = find(a);
        int y = find(b);
        if (x != y)
        {
            roots[y] = x;
        }
    }
    int count()
    {
        set<int> s;
        for (int k = 1; k <= length; k++)
        {
            s.insert(roots[k]);
        }
        return s.size();
    }
};
struct Point
{
    int x;
    int y;
};
int main()
{
    int n;
    cin >> n;
    UnionSet us(n);
    Point *point = new Point[n + 1];
    for (int i = 1; i <= n; i++)
    {
        cin >> point[i].x >> point[i].y;
    }
    for (int i = 1; i < n; i++)
    {
        for (int j = i + 1; j <= n; j++)
        {
            if (point[i].x == point[j].x || point[i].y == point[j].y)
            {
                us.merge(i, j);
            }
        }
    }
    cout << us.count() - 1 << endl;
    return 0;
}
相关文章
|
2月前
|
容器
数据结构:并查集
数据结构:并查集
24 0
数据结构:并查集
|
2天前
|
算法 索引
数据结构与算法-并查集多种实现以及优化步骤
数据结构与算法-并查集多种实现以及优化步骤
5 0
|
2月前
|
算法 计算机视觉
【数据结构入门精讲 | 第十六篇】并查集知识点及考研408、企业面试练习
【数据结构入门精讲 | 第十六篇】并查集知识点及考研408、企业面试练习
28 0
|
4月前
|
算法 Python
Python高级数据结构——并查集(Disjoint Set)
Python高级数据结构——并查集(Disjoint Set)
121 2
|
8月前
|
存储 Java
Java数据结构之第十六章、并查集
Java数据结构之第十六章、并查集
63 0
|
9月前
|
存储
|
10月前
|
存储 算法 Java
【Java高阶数据结构】并查集-最小生成树
Java高阶数据结构 & 并查集 & 最小生成树 1. 并查集 1.1 并查集的原理 在一些应用问题中,我们常常会遇到一类问题 一开始是一个人 后来新增的人可能与这个人有关系,也可能与这个人无关系。 一个人与一个人有关系,这个人与另一个人也有关系,那么三人都有关系。 有关系的和没关系的之间是不同的类别。
84 0
|
11月前
数据结构-并查集-2
四、并查集例题——连通块中点的数量
|
11月前
|
存储 Python
数据结构-并查集
数据结构-并查集
|
存储 算法
【数据结构与算法】并查集
【数据结构与算法】并查集
【数据结构与算法】并查集