杭电ACM省赛集训队选拔赛之热身赛-How Many Tables,并查集模板题~~

How Many Tables

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)


Problem Description
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 4

       刚学并查集,就以这道题为例题了,并查集没学会怎么学生成树啊,,起初是想做”引水工程“这道省赛题的,结果发现要用最小生成树,,奈何汝家不会,所以发了半天时间看并查集。大一上学期是学过并查集的,但当时什么都没听懂,稀里糊涂的,还是靠自己学会,讲了克鲁斯卡尔与普里姆算法,但克鲁斯卡尔算法实现起来更简单一点;

      感觉应该是最基本的并查集了,要不然代码也不会这么短;

#include
#include
#include
#include
#include
#include
using namespace std;
const int N=1000+10;
int n,m,a,b,p[N];
int find(int x)
{
    return p[x]==x?x:p[x]=find(p[x]);//递归寻找根节点,时间复杂度几乎为常数;
}
void ks()
{
    for(int i=1; i<=n; i++)
        p[i]=i;//先初始化,每个节点初始的根节点都是本身,当两个节点有联系时就可以合并起来,最终形成树;
    while(m--)
    {
        scanf("%d%d",&a,&b);
        int x=find(a),y=find(b);
        if(x!=y)
        {
            p[y]=x;//合并,建议模拟第一组测试数据更好理解;
            n--;//一旦可以合并说明可以省下一张桌子(最初需要桌子数就等于总人数);
        }
    }
}
int main()
{
    int t,i;
    scanf("%d",&t);
    while(t--)
    {
        memset(p,0,sizeof(p));
        scanf("%d%d",&n,&m);
        ks();
        printf("%d\n",n);
    }
    return 0;
}

   详细分解请看小白书201业(算法入门经典),或者百度全面知识,大一菜鸟新人求罩

   created at 2016.4.7-21:12


你可能感兴趣的:(ACM进阶之树论,HDU)