HDU-1213 How Many Tables

本文介绍了一个使用并查集算法解决生日派对安排问题的方法。问题设定为需要根据朋友之间的熟悉程度来确定最少需要准备多少张桌子。通过构建并查集,实现了对朋友关系的有效管理和合并,最终得出需要的桌子数量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

题目大意:某人生日派对,给定T组测试样例,N为参与派对朋友的数量,M为线索的数量,线索是指编号为A,B的两人互相认识。朋友的朋友也是朋友。互相认识的可以坐一桌,否则不可以。问需要准备几桌?
思路 :基础的并查集,由于这是我第一次解决并查集问题,所有来个奠基性质的博文。建立一个一维数组,数组下标代表编号,值代表该编号的“老大”,合并每一个人的老大看最后能组成多少个互不相干的朋友圈。这里说下并查集的原则,在啊哈算法中形容为“”靠左法则——指两个人如果互不相识则右边认左边为老大,和“擒贼先擒王法则”,——指每次让老大互相投靠即可,小BOSS的老大会在函数递归过程中被修改(路径压缩)。
代码如下:

#include<iostream>
#include<cstring>
using namespace std;
int father[1010]={0};
int getf(int m)
{
  if(m==father[m])return m;//我就是老大
  else return father[m]=getf(father[m]);//我不是老大,要找老大(路径压缩,将途中
  //遇到的人的老大都改为最终老大,提高今后找老大的速度)
}
void merge(int a,int b)
{
  int t1=getf(a);//找到a的老大
  int t2=getf(b);//找到b的老大
  if(t1!=t2)//老大不一样
  {
  //  father[b]=t1;//b投靠a的老大
    father[t2]=t1;//b的老大也投靠a的老大
  }
}
int main()
{
  int t;
  cin>>t;
  while(t--)
  {
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=n;i++)father[i]=i;//初始化,所有人互不相识
    for(int i=0;i<m;i++)
    {
      int a,b;
      cin>>a>>b;
      merge(a,b);//合并朋友圈
    }
    int sum=0;
    for(int i=1;i<=n;i++)if(father[i]==i)sum++;//统计有多少个独立的朋友圈
    cout<<sum<<endl;
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值