1. 程式人生 > >查並集(How Many Tables)

查並集(How Many Tables)

在初高中數學中我們都學過集合,也就知道集合的交集和並集。所以思路應該很明確,但是用程式碼表示要注意一下幾個坑:

1)兩個集合中可能有重複的元素,一定要查重;

2)兩個集合合併,一定要將兩個集合的所有元素都歸到一個集合內;

 用一個經典的查並集演算法題來解釋一下

How Many Tables(並查集)

Link:https://cn.vjudge.net/contest/175491#problem/D

題目:

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


5 3 
1 2 
2 3 
4 5

5 1 
2 5

Sample Output


4

思路:每個人是一個數組,兩個陣列記憶體的數如果相同,代表認識併成為一桌;(每個陣列內剛開始都是自身編號)

給你們一組特殊測試資料:

輸入:

1

5 4

1 2

1 3

4 3

3 4

輸出:

2

程式碼內部講解:

#include<iostream>
#include<cstdio>
int s[1005];
int n,m,i;
void chongzhi()//將每個人陣列內的數重置一下  剛開始都是自身編號
{
    for(i=1;i<=n;i++)
    {
        s[i]=i;
    }
}
int bing(int x)//其實這個函式可以省略 只是為了更加清晰
{
    if(x==s[x])//如果陣列內的數跟自身相同 就返回自身的數
    {
        return x;
    }
    return bing(s[x]);//如果不同 返回陣列記憶體的數
}
int he(int x,int y)
{
    int t1=bing(x);
    int t2=bing(y);
    int t;
    if(t1!=t2)//如果兩個陣列的數不相同 將他們合併集合
    {
        t=s[t2];
        s[t2]=s[t1];
        for(i=1;i<=n;i++)//這個迴圈就是為了將 兩個集合的所有元素合併 不僅僅是兩個元素合併
        {
            if(s[i]==t)
            {
                s[i]=s[t1];
            }
        }
    }

}
int main()
{
    int t,j,k,l;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d %d",&n,&m);//n個人 m個數據
        chongzhi();//呼叫上面的函式 將每個人陣列內的數重置一下  剛開始都是自身編號
        int a,b;
        while(m--)
        {
            scanf("%d %d",&a,&b);
            s[a]=bing(a);
            s[b]=bing(b);
            he(s[a],s[b]);//合併集合
        }
        for(j=1;j<=n;j++)//排序
        {
            for(k=1;k<=n-j;k++)
            {
                if(s[k]>s[k+1])
                {
                    l=s[k];
                    s[k]=s[k+1];
                    s[k+1]=l;
                }
            }
        }
        l=1;
        for(j=1;j<n;j++)//查重
        {
            if(s[j]!=s[j+1])
                l++;
        }
        printf("%d\n",l);//輸出剩餘
    }
}