简单并查集

描述

给定一个包含 N 个顶点 M 条边的无向图 G ,判断 G 是不是一棵树。

输入

第一个是一个整数 T ,代表测试数据的组数。 (1 ≤ T ≤ 10)

每组测试数据第一行包含两个整数 N 和 M 。(2 ≤ N ≤ 500, 1 ≤ M ≤ 100000)

以下 M 行每行包含两个整数 a 和 b ,表示顶点 a 和顶点 b 之间有一条边。(1 ≤ ab ≤ N)

输出

对于每组数据,输出YES或者NO表示 G 是否是一棵树。

样例输入
2
3 2
3 1
3 2
5 5
3 1
3 2
4 5
1 2
4 1 
样例输出
YES
NO
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#define MAX 501
#define Max(a,b) ((a)>(b)?(a):(b))
using namespace std;

int G[MAX];//存储根节点
int E[MAX];//判断是否访问过该节点

int find(int x)
{
	if (G[x] != x)
		G[x] = find(G[x]);
	return G[x];
}

int U(int x, int y)
{
	int fx = find(x);
	int fy = find(y);

	if (fx == fy)
		return false;
	G[fy] = fx;
	return true;
}

int main()
{
	int i, T;
	int N, M;
	int a, b;

	cin >> T;
	while (T--)
	{
		cin >> N >> M;
		bool flag = true;
		int sum = 0;
		int max = 0;
		for (i = 0; i < MAX; i++)
			G[i] = i;
		memset(E, 0, sizeof(E));
		for (i = 0; i < M; ++i)
		{
			cin >> a >> b;
			E[a] = 1;
			E[b] = 1;
			max = Max(max, Max(a, b));
			if (!U(a, b))
				flag = false;
		}
		for (i = 0; i < max; ++i)
		{
			if (E[i] == 1 && G[i] == i)
				++sum;
		}
		if (sum > 2)
			flag = false;
		cout << ((flag) ? ("YES") : ("NO")) << endl;
	}
    return 0;
}
/*
5
3 2
3 1
3 2

5 5
3 1
3 2
4 5
1 2
4 1

8 6
3 8
6 8
6 4
5 3
5 6
5 2

*/


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值