并查集算法----犯罪团伙(黑科技)

一、题目描述

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

输入
 第1行:n(<=500,罪犯数量),m(<50000,关系数量)以下m行:每行两个数:i 和j,中间一个空格隔开,表示罪犯i和罪犯j相互认识。


输出
 第1行:一个整数,犯罪团伙的数量。

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

样例输出
3



二、分析

我最开始的想法是用图论算法,但是想了半天都没有思路,然后就用搜索算法来做,结果,一搜索就死循环。

最后干脆用循环来做,

基本思想(样例): 

1 2 3 4 5 6 7 8 9 10 11(代表11 个人)

1 2 3 4 5 6 7 8 9 10 11(代表这11个人的老板)

输入:1 2 (理解为 2的老板是1)

1 2 3 4 5 6 7 8 9 10 11

1 1 3 4 5 6 7 8 9 10 11

输入:4 3 (理解为 3的老板是4)

1 2 3 4 5 6 7 8 9 10 11

1 1 4 4 5 6 7 8 9 10 11

输入:5 4 (理解为 4的老板是5)

1 2 3 4 5 6 7 8 9 10 11

1 1 5 5 5 6 7 8 9 10 11

……(以此类推)

最终结果:

1 2 3 4 5 6 7 8 9 10 11

1 1 1 1 1 1 1 8 8 1 11

犯罪团伙:1、8和11。

#include<cstdio>
int a[505],b[505],f[505];
int main()
{
	//freopen("gang.in","r",stdin);
	//freopen("gang.out","w",stdout);
	int m,n,i,j,x,y,sum=0,k;
	scanf("%d%d",&n,&m);
	for(i=1;i<=n;i++){
		a[i]=i;
		b[i]=i;
	}
	for(i=1;i<=m;i++){
		scanf("%d%d",&x,&y);
		k=b[y];//注意b[y]的值会改变
		for(j=1;j<=n;j++){
			if(b[j]==k){
				b[j]=b[x];
			}
		}
	}
	for(i=1;i<=n;i++){
		f[b[i]]=1;
	}
	for(i=1;i<=n;i++){
		if(f[i]==1)
			sum++;
	}
	printf("%d",sum);
}

后来发现:a数组完全没有用,f数组也可以进行优化,

最终代码:

#include<cstdio>
int b[505];
int main()
{
	//freopen("gang.in","r",stdin);
	//freopen("gang.out","w",stdout);
	int m,n,i,j,x,y,sum=0,k;
	scanf("%d%d",&n,&m);
	for(i=1;i<=n;i++){
		b[i]=i;
	}
	for(i=1;i<=m;i++){
		scanf("%d%d",&x,&y);
		k=b[y];
		for(j=1;j<=n;j++){
			if(b[j]==k){
				b[j]=b[x];
			}
		}
	}
	for(i=1;i<=n;i++){
		if(b[i]==i)
			sum++;
	}
	printf("%d",sum);
}

后来听别人说,这就是并查集算法。

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