并查集

题意

现在有11个强盗。

1号强盗与2号强盗是同伙。
3号强盗与4号强盗是同伙。
5号强盗与2号强盗是同伙。
4号强盗与6号强盗是同伙。
2号强盗与6号强盗是同伙。
7号强盗与11号强盗是同伙。
8号强盗与7号强盗是同伙。
9号强盗与7号强盗是同伙。
9号强盗与11号强盗是同伙。
1号强盗与6号强盗是同伙。
有一点需要注意:强盗同伙的同伙也是同伙。
请能帮助警方查出有多少个独立的犯罪团伙

首先我们假设这11个强盗相互是不认识的,他们各自为政,每个人都是首领,他们只听从自己的。之后我们将通过警方提供的线索,一步步地来“合并同伙”。

第一步:我们申请一个一维数组f,我们用f[1]f[11]分别存储111号强盗中每个强盗的首领“BOSS”是谁。

第二步:初始化。根据我们之前的约定,这11个强盗最开始是各自为政的,每个强盗的BOSS就是自己。“1号强盗”的BOSS就是“1号强盗”自己,因此f[1]的值为1。以此类推,“11号强盗”的BOSS是“11号强盗”,即f[11]的值为11。我们用数组下标来表示强盗的编号,每个单元格中存储的是每个强盗的“BOSS”是谁。

第三步:开始“合并同伙”,即如果发现目前两个强盗是同伙,则这两个强盗是同一个犯罪团伙。例如警方得到的第1条线索是“1号强盗与2号强盗是同伙”。“1号强盗”和“2号强盗”原来的BOSS都是自己,如今发现“1号强盗”和“2号强盗”其实是同一个犯罪团伙,那么究竟是让“1号强盗”变成“2号强盗”的BOSS,还是让“2号强盗”变成“1号强盗”的BOSS呢?一个犯罪团伙只能有一个首领。其实无所谓,都可以。我们这里假定左边的强盗更厉害一些,给这个规定起个名字叫作“靠左”法则(注意靠左法则,左指的是在一开始)。也就是说“2号强盗”的BOSS将变成“1号强盗”。因此我们将f[2]中的数改为1,表明“2号强盗”归顺了“1号强盗”。其实准确地说应该是原本归顺“2号强盗”的所有人都归顺了“1号强盗”才对,只不过此时“2号强盗”只孤身一人,因此只需要将f[2]的值改为1。

#include
using namespace std;
int f[1000]={0};
int n,m ,k,sum=0;
void init()
{
	for(int i=1;i<=n;i++)
	{
		f[i]=i;
	}
	return;
}
int getf(int v)
{
	if(f[v]==v)
		return v;
	else 
	{
		f[v]=getf(f[v]);
		return f[v];
	}
}
void merge(int v,int u)
{
	int t1,t2;
	t1=getf(v);
	t2=getf(u);
	if(t1!=t2)
	{
		f[t2]=t1;
	}
	return;
}
int main()
{
	int x,y;
	cin>>n>>m;
	init();
	for(int i=1;i<=m;i++)
	{
		cin>>x>>y;
		merge(x,y);
	}
	for(int i=1;i<=n;i++)
	{
		if(f[i]==i)
			sum++;
	}
	cout<<sum<<endl;
	return 0;
}

你可能感兴趣的:(算法,c++)