SHUOJ几队周尼玛
描述
超级无敌张小豪是A国的一名勇士,A国的勇士都要靠获得能量变得更强,在A国勇士获得能量只有唯一的一种途径就是膜拜宙斯神——周尼玛(桑!!!)。要膜拜周尼玛就要去到遥远的大日国那里有好多好多周尼玛(桑!!!)。但是周尼玛(桑!!!)是一种群居动物,一队周尼玛(桑!!!)中都有且只有一个领袖叫周尼玛你妹(桑!!!)超级无敌张小豪勇士必须拿着一炷香到周尼玛你妹(桑!!!)面前膜拜三下即可获得一点能量。
膜拜必须遵循一些规则:
对于一个周尼玛你妹(桑!!!)只能膜拜一次;
不能膜拜周尼玛(桑!!!);
一次膜拜用一炷香且一炷香只能膜拜一次;
现在问题出现了,小豪准备启程去大日国,在走之前小豪要准备买香但是小豪不知道大日国一共有几队周尼玛(桑!!!),小豪既想每个周尼玛你妹(桑!!!)都膜拜到,又想带过去的香能用完不浪费。于是小豪打听小道消息搞过来了一张周尼玛(桑!!!)家族谱。
家族谱上有若干对数字
eg:
1 2
2 4
表示:
周尼玛1号和周尼玛2号是一队的
周尼玛2号和周尼玛4号是一队的
若谱上告诉你周尼玛x号和周尼玛y号是一队的周尼玛y号和周尼玛z号是一队的
那也就代表了周尼玛x号和周尼玛z号是一队的了。
输入
The input starts with an integer T(1<=T<=10) which indicate the number of test cases. Then T test cases follow. Each test case starts with two integers N and M(1<=N<= 30000,1<=M<= 500000). N indicates the number of 周尼玛, the 周尼玛 are marked from 1 to N. Then M lines follow. Each line consists of two integers A and B(A!=B), that means 周尼玛 A号 and 周尼玛 B号 in the same team. There will be a blank line between two cases.
输出
For each test case, just output how many tables Ignatius needs at least. Do NOT print any blanks.
样例输入
2
5 3
1 2
2 3
4 5
5 1
2 5
样例输出
2
4
我的想法
自作幽默还特别懒的出题人扯了这么多,讲的意思其实就是在n个人中有人相互认识,且大家可以通过中间人相互认识,最后属于同一张关系网的人归为一队,问这么分下来有几队人。这就是HDU1213题,一个关于并查集的基本问题。当时想这个问题和找资料花了很久时间,毕竟是什么都没学的萌新。
我的想法是对于每行数据中一对相互认识的人a和b,将b的根节点值赋给a的根节点。最终有多少根节点就有多少队。
关于并查集的问题查了很多资料,也看了很多大佬的博客,感觉最有帮助的还是这篇[并查集]文末有给出链接,讲的肯定比我清楚多了,当然也不能直接用在这道题里。
我的代码如下
代码
#include<stdio.h>
int root[30005];
void mix(int x,int y);
int tree(int x);
int main()
{
int t,n,m;
int i,j,k,cnt;
int x,y;
scanf("%d",&t);
for(i=0;i<t;i++)
{
cnt=0;
scanf("%d %d",&n,&m);
for(j=1;j<=n;j++)
root[j]=j;
for(j=0;j<m;j++)
{
scanf("%d %d",&x,&y);getchar();
mix(x,y);
}
for(k=1;k<=n;k++)
{
if(k==root[k])
cnt=cnt+1; //发现根节点就计数
}
printf("%d\n",cnt);
}
return 0;
}
int tree(int x)//根节点赋值+路径压缩
{
int a=x;
while(a!=root[a])
a=root[a];
int i=x,j;
while(i!=a)
{
j=root[i];
root[i]=a;
i=j;
}
return a;
}
void mix(int x,int y)//相互认识,修改根节点
{
int fx=tree(x),fy=tree(y);
if(fx!=fy)
root[fx]=fy;
}
引用和资料
并查集
http://blog.csdn.net/love_gaohz/article/details/74857328