SHUOJ几队周尼玛

来源:互联网 发布:知乎 室内环保 编辑:程序博客网 时间:2024/05/11 15:35

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

原创粉丝点击