zoukankan      html  css  js  c++  java
  • 九度 1526:朋友圈(并查集)

    题目描述:

    假如已知有n个人和m对好友关系(存于数字r)。如果两个人是直接或间接的好友(好友的好友的好友...),则认为他们属于同一个朋友圈,请写程序求出这n个人里一共有多少个朋友圈。
    假如:n = 5 , m = 3 , r = {{1 , 2} , {2 , 3} , {4 , 5}},表示有5个人,1和2是好友,2和3是好友,4和5是好友,则1、2、3属于一个朋友圈,4、5属于另一个朋友圈,结果为2个朋友圈。

    思路

    1. 裸的并查集, 回顾下并查集的知识

    2. 并查集主要有两个操作, 一个是 merge, 一个是 find. find 用于找到一个集合的标志, merge 用于合并两个集合. 在实际的操作中, 我们只要用 merge 就好了, find 不直接使用

    3. find 又有路径压缩的说法, 这是在寻找集合标志的过程中, 使得这条路径上的所有节点到标志的距离都压缩成 1, 使用递归完成

    4. 比较来了两个节点 0 1, 我们要做的就是 merge(0,1), 将 0, 1 合并到一个集合中. merge 的实际操作是将两个集合的标志建立父子关系

    代码

    #include <iostream>
    #include <stdio.h>
    using namespace std;
    
    int father[100010];
    
    int find(int x) {
        if(father[x] != x) {
            father[x] = find(father[x]);
        }
        return father[x];
    }
    
    void merge(int a, int b) {
        int fa = find(a);
        int fb = find(b);
        if(fa == fb)
            return;
        father[fa] = fb;
    }
    
    int main() {
        //freopen("testcase.txt", "r", stdin);
        int n, m;
        while(scanf("%d", &n) && n != 0) {
            scanf("%d", &m);
            for(int i = 1; i <= n; i ++)
                father[i] = i;
    
            int a, b;
            for(int i = 0; i < m; i ++) {
                scanf("%d%d", &a, &b);
                merge(a,b);
            }
            int cnt = 0;
            for(int i = 1; i <= n; i ++) {
                if(father[i] == i)
                    cnt++;
            }
            cout << cnt << endl;
        }
        return 0;
    }
  • 相关阅读:
    力扣算法题—091解码
    力扣算法题—090子集2
    力扣算法题—089格雷编码
    力扣算法题—088合并两个有序数组
    HDU 1509 Windows Message Queue
    HDU 1241 Oil Deposits
    HDU 1096 A+B for Input-Output Practice (VIII)
    HDU 1108 最小公倍数
    HDU 1106 排序
    HDU 1003 Max Sum * 最长递增子序列(求序列累加最大值)
  • 原文地址:https://www.cnblogs.com/xinsheng/p/3581057.html
Copyright © 2011-2022 走看看