ACM-并查集- How Many Tables-HDU - 1213

D - How Many Tables


Today is Ignatius' birthday. He invites a lot of friends. Now it's dinner time. Ignatius wants to know how many tables he needs at least. You have to notice that not all the friends know each other, and all the friends do not want to stay with strangers. 

One important rule for this problem is that if I tell you A knows B, and B knows C, that means A, B, C know each other, so they can stay in one table. 

For example: If I tell you A knows B, B knows C, and D knows E, so A, B, C can stay in one table, and D, E have to stay in the other one. So Ignatius needs 2 tables at least. 

Input

The input starts with an integer T(1<=T<=25) which indicate the number of test cases. Then T test cases follow. Each test case starts with two integers N and M(1<=N,M<=1000). N indicates the number of friends, the friends are marked from 1 to N. Then M lines follow. Each line consists of two integers A and B(A!=B), that means friend A and friend B know each other. There will be a blank line between two cases. 

Output

For each test case, just output how many tables Ignatius needs at least. Do NOT print any blanks. 

Sample Input

2
5 3
1 2
2 3
4 5

5 1
2 5
Sample Output

2

扫描二维码关注公众号,回复: 945399 查看本文章

4

/*注意这个题很简单就是个并查集的模板题

有几个点需要特殊注意一下,这个不是带权并查集,所以不用和食物链那道题一样对不同元素之间的不同关系用数字去区分

1.main()函数里面两个for循环以及初始化时的for循环,都不是从0开始,因为数字是从1-n的所以范围应该改成for(int i=1;i<=n;i++){....}

2.只需要计算里面有多少个不同的根即知道有多少个连通分支,即所求

3.里面的mark[]数组是用来标记根节点的,初始化的时候都设置为0

4.注意注意!!!!里面输入N,M,a,b的时候千万不能加空格,不然输出的时候一定会出错!!!!!


C++源代码

#include <iostream>
#include <stdio.h>
#include <cstring>
using namespace std;
int T,N,M;


int pre[1005];


//初始化
void init(int n){
    for(int i=1;i<=N;i++){
        pre[i]=i;
    }
}


int find(int x){
   int r=x;
   //使得r代表x的根节点
   while(r!=pre[r]){
       r=pre[r];
   }
   int j=x;
   //使得x的所有父节点的父节点都变成根节点
   while(x!=r){
       j=pre[x];
       pre[x]=r;
       x=j;
   }
   return r;
}


void unite(int a,int b){
    int x1=find(a);
    int y1=find(b);
    if(x1!=y1){
        pre[y1]=x1;
    }
}
int main()
{
    scanf("%d",&T);
    int mark[1005];
    while(T--){
        scanf("%d%d",&N,&M);
        init(N);
        int ans=0;
        //用来标记根节点,如果是根节点则值不为0
        memset(mark,0,sizeof(mark));//初始化mark数组
        while(M--){
            int a,b;
            scanf("%d%d",&a,&b);
            unite(a,b);
        }
        for(int i=1;i<=N;i++){
          int r=find(i);
          mark[r]=1;
        }
        for(int i=1;i<=N;i++){
           if(mark[i]){
               ans++;
           }
        }
        printf("%d\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_39525042/article/details/75210751