codevs[3554]犯罪团伙

@犯罪团伙

题目大意

  有n(n<=10000)个罪犯以及m(m<100000)组罪犯间的关系,每个犯罪团伙中的罪犯间都相互或间接相互认识,现求这些罪犯中共存在多少个犯罪团伙。当然,也有可能一个犯罪团伙只有一个人。

输入输出

输入有若干行
第一行为罪犯数量n
第二行为关系数量m
接下来的m行每行有两个用空格隔开的数,表示某两个罪犯相互认识

输出有一行,表示犯罪团伙的数量

样例输入:

11
8
1 2
4 5
3 4
1 3
5 6
7 10
5 10
8 9


样例输出:

3

算法讨论

  这题可以使用并查集解决。我们可以建立一个数组father[10000]来表示罪犯i与罪犯father[i]在一个团伙中。然后,每当我们输入一组罪犯关系”a b”时,将将a赋值给father[b]。这样操作直到输入完成后,我们就得到了一棵棵代表犯罪团伙的树。
  接着定义一个初始值为0的变量gang,用它来统计犯罪团伙总数。然后从1到n遍历father。如果father[i]==i,就说明这是一个犯罪团伙的根结点,那么就gang++,最后将gang输出即可。

代码实现

#include <iostream>
#include <cstdio>
using namespace std;
int father[100000] = {0};

int find(int x){ //查找祖先结点
    if (father[x] != x) father[x] = find(father[x]);
    return father[x];
}

void Merge(int a, int b){ //合并两个集合
    father[find(b)] = find(a);
}

int main(){

    int m, n, counting = 0;
    scanf("%d %d", &n, &m);

    for (int i = 1; i <= n; i++) 
        father[i] = i; //初始化犯罪团伙
    for (int i = 0; i < m; i++) {
        int a, b;
        scanf("%d %d", &a, &b);
        Merge(a, b); //合并犯罪团伙
    }
    for (int i = 1; i <= n; i++)
        if (father[i] == i) counting++; //计算数量

    printf("%d\n", counting);
    return 0;

}
    原文作者:犯罪团伙问题
    原文地址: https://blog.csdn.net/qq_19473975/article/details/76147187
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞