【赛码】认老乡
题目描述
大学的同学来自全国各地,对于远离家乡步入陌生大学校园的大一新生来说,碰到老乡是多么激动的一件事,于是大家都热衷于问身边的同学是否与自己同乡,来自新疆的小赛尤其热衷。但是大家都不告诉小赛他们来自哪里,只是说与谁同乡,从所给的信息中,你能告诉小赛有多少人确定是她的同乡吗?
赛码网题目链接:点击这里
输入
每个测试实例首先包括2个整数,N(1 <= N <= 1000),M(0 <= M <= N*(N-1)/2),代表现有N个人(用1~N编号)和M组关系;
在接下来的M行里,每行包括2个整数,a,b,代表a跟b是同乡;
当N = 0,M = 0输入结束;
已知1表示小赛本人。
样例输入
3 1
2 3
5 4
1 2
3 4
2 5
3 2
0 0
输出
对于每个测试实例,输出一个整数,代表确定是小赛同乡的人数。
样例输出
0
4
#include<iostream>
using namespace std;
#define N 1001
int person[N];
//根据元素查找集合名
int find(int x)
{
if(person[x]<0)
return x;
else
return find(person[x]);
}
//合并集合名
void unionset(int root1, int root2)
{
person[root2]=root1;
}
int main()
{
int n,m,a,b;
while(cin>>n>>m)
{
if(n==0 && m==0)
break;
//n个人初始化
for(int i=1; i<=n; i++)
{
person[i]=-1;
}
//处理m组关系
for(int i=0; i<m; i++)
{
cin>>a>>b;
if(find(a)!=find(b))
unionset(find(a),find(b));
}
//查找和计数
int result=0;
int target=find(1);
//遍历检查
for(int i=1; i<=n; i++)
{
if(find(i)==target)
result++;
}
cout<<result-1<<endl;
}
return 0;
}
说明:
1. 改进之处:可以将存储的负值变成集合的大小和树的高度,从而减少查询的次数。