Ubiquitous Religions
当今世界有许多不同的宗教,很难跟踪它们。你有兴趣找出你大学里有多少不同的宗教学生相信。
你知道你的大学里有 n 学生 (0 < n < = 50000) 。你问每个学生他们的宗教信仰是不可行的。此外,许多学生不愿意表达他们的信仰。避免这些问题的一种方法是询问 m (0 <= m <= n (n-1)/2) 对学生,并询问他们是否相信同一宗教(例如,他们可能知道他们是否都在同一个教会)。从这些数据中,你可能不知道每个人相信什么,但你可以了解有多少不同的宗教可以在校园里代表的上限。你可以假设每个学生最多订阅一种宗教。输入
输入包括多个案例。每个案例都以指定整数 n 和 m 的行开始。下一行由两个整数 i 和 j 组成, 指定学生 i 和 j 相信同一宗教。学生人数为1比1。输入的末端由 n = m = 0 的行指定。
输出
对于每个测试案例,在一行打印案例编号(从 1 开始),然后打印大学学生所信仰的不同宗教的最大数量。
示例输入
10 9
1 2
1 3
1 4
1 5
1 6
1 7
1 8
1 9
1 10
10 4
2 3
4 5
4 8
5 8
0 0
样品输出
Case 1: 1
Case 2: 7
提示
巨大的输入,建议扫描。
题意描述:多实例,给学生人数以及要询问的学生对数,然后是学生相信同一宗教的学生编号,求所有学生信仰的宗教总数
解题思路:利用并查集求学生相信宗教的不相交集合,然后求一共有多少个集合即可。
AC
#include<stdio.h>
int n,m;
int s[50100]={0};
void init()
{
for(int i=1;i<=n;i++)
s[i]=i;
return ;
}
//递归找爹 合并给的道路
int getf(int v)
{
if(s[v]==v)
return v;
else
{
//路径压缩
s[v]=getf(s[v]);
return s[v];
}
}
//合并两个子集
void merge(int v,int u)
{
int t1,t2;
t1=getf(v);
t2=getf(u);
if(t1!=t2)
{
s[t2]=t1;
}
return ;
}
int main(void)
{
int a,b,sum,ans;
ans=0;
while(~scanf("%d %d",&n,&m))//学生,询问对数
{
if(n+m==0)
break;
ans++;
init();//初始化
for(int i=1;i<=m;i++)
{
scanf("%d %d",&a,&b);
//合并
merge(a,b);
}
sum=0;
//扫描多少个块;
for(int i=1;i<=n;i++)
{
if(s[i]==i)
sum++;
}
printf("Case %d: %d\n",ans,sum);
}
return 0;
}