题目概述
给定N个人,编号1到N,如果两个人都认识同一个人,那么这两个人也视为互相认识,给定M条这样的关系,若只能将互相认识的人安排到同一张桌子,问最少需要多少桌子
自己必然认识自己,因而不会出现这样的数据
时限
1000ms/2000ms
输入
第一行正整数times,其后有times组数据,每组数据第一行正整数N,M,其后M行,每行两个正整数,代表这两个人互相认识,两组输入中间带一空行
限制
1<=times<=25;1<=N,M<=1000
输出
每行一个数,为所求最少桌子数
样例输入
2
5 3
1 2
2 3
4 5
5 1
2 5
样例输出
2
4
讨论
并查集,已经足够水了,额不想多说什么了
题解状态
0MS,1716K,1117 B,C++
题解代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define INF 0x3f3f3f3f
#define MAXN 1003
#define memset0(a) memset(a,0,sizeof(a))
struct UF//union_find 并查集的结构 习惯性带上路径压缩 以前也用过多次了
{
int cnt, id[MAXN], sz[MAXN];//独立的树数 父节点下标 树所带的节点数
UF(int N)//构造
{
for (int p = 0; p < N; p++) {
id[p] = p;
sz[p] = 1;
}
cnt = N;
}
int UFfind(int a)//查根
{
int p = a;
while (a != id[a])
a = id[a];
id[p] = a;
return a;
}
bool UFconnected(int a, int b)//连通
{
return UFfind(a) == UFfind(b);
}
void UFunion(int a, int b)//合并
{
int p = UFfind(a), i = UFfind(b);
if (p == i)
return;
if (sz[p] < sz[i]) {
id[p] = i;
sz[i] += sz[p];
}
else {
id[i] = p;
sz[p] += sz[i];
}
cnt--;
}
};
int fun(int N, int M)
{
UF uf(N + 1);//没有0号 但要初始化上
for (int p = 0; p < M; p++) {
int a, b;
scanf("%d%d", &a, &b);//input
uf.UFunion(a, b);
}
return uf.cnt - 1;//没有0号 他总是独占一棵树
}
int main(void)
{
//freopen("vs_cin.txt", "r", stdin);
//freopen("vs_cout.txt", "w", stdout);
int times;//数据组数
scanf("%d", ×);//input
while (times--) {
int N, M;//总人数 给出的关系数
scanf("%d%d", &N, &M);//input
printf("%d\n", fun(N, M));//output
}
}
EOF