犯罪团伙

警察抓到了n 个罪犯,警察根据经验知道他们属于不同的犯罪团伙,却不能判断有多少个团伙,但通过警察的审讯,知道其中的一些罪犯之间相互认识,已知同一犯罪团伙的成员之间直接或间接认识。有可能一个犯罪团伙只有一个人。请你根据已知罪犯之间的关系,确定犯罪团伙的数量。已知罪犯的编号从1 至n。

【输入】
第一行:n(<=1000,罪犯数量),
第二行:m(<5000,关系数量)
以下若干行:每行两个数:I 和j,中间一个空格隔开,表示罪犯i 和罪犯j 相互认识。

【输出】
一个整数,犯罪团伙的数量。

样例输入:
11
8
1 2
4 3
5 4
1 3
5 6
7 10
5 10
8 9

输出:
3

说明:共三个犯罪团伙。

 

这道题一眼就能看出来就是并查集水题。并查集板子一贴,然后统计一下有多少个根节点就行了。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<cmath>
 5 #include<algorithm>
 6 using namespace std;
 7 #define rep(i, a, n) for(int i = a; i <= n; ++i)
 8 #define per(i, n, a) for(int i = n; i >= a; --i)
 9 typedef long long ll;
10 const int maxn = 5e3 + 5;
11 
12 int p[maxn], vis[maxn];
13 void init()
14 {
15     rep(i, 1, maxn - 1) p[i] = i; return;
16 }
17 int Find(int x)
18 {
19     return x == p[x] ? x : p[x] = Find(p[x]);
20 }
21 void merge(int x, int y)
22 {
23     int px = Find(x), py = Find(y);
24     if(px == py) return;
25     else {p[px] = py; return;}
26 }
27 int n, m;
28 int ans = 0;
29 int main()
30 {
31     freopen("gang.in", "r", stdin);
32     freopen("gang.out", "w", stdout);
33     init();
34     scanf("%d%d", &n, &m);
35     rep(i, 1, m)
36     {
37         int x, y; scanf("%d%d", &x, &y);
38         merge(x, y);
39     }
40     rep(i, 1, n) 
41         if(!vis[Find(i)]) {ans++; vis[Find(i)]++;}
42     printf("%d\n", ans);
43     return 0;
44 }

 

posted @ 2018-03-21 19:04  mrclr  阅读(343)  评论(0编辑  收藏  举报