SHUOJ几队周尼玛

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

猜你喜欢

转载自blog.csdn.net/waveviewer/article/details/75578791