4216. 图中的环

题目链接

4216. 图中的环

给定一个 \(n\) 个点 \(m\) 条边的无向图。

点的编号从 \(1\)\(n\)

图中不含重边和自环。

请你对给定图进行判断,如果该图是一个有且仅有一个环的连通图,则输出 YES,否则输出 NO

输入格式

第一行包含两个整数 \(n,m\)

接下来 \(m\) 行,每行包含两个整数 \(a,b\),表示点 \(a\) 和点 \(b\) 之间存在一条无向边。

输出格式

如果该图是一个有且仅有一个环的连通图,则输出 YES,否则输出 NO

数据范围

前三个测试点满足 \(1≤n≤10\)
所有测试点满足 \(1≤n≤100\)\(0≤m≤ \frac{n(n−1)}{2}\)\(1≤a,b≤n\)

输入样例1:

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

输出样例1:

YES

输入样例2:

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

输出样例2:

NO

解题思路

基环树

一棵树为基环树的充要条件:

  1. 连通
  2. 点数=边数

显然,题目要求的便是判断一棵树是否为基环树,点数=边数可以直接判断,连通可用并查集判断

  • 时间复杂度:\(O(nlogn)\)

代码

// Problem: 图中的环
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/4219/
// Memory Limit: 256 MB
// Time Limit: 1000 ms

// %%%Skyqwq
#include <bits/stdc++.h>

#define pb push_back
#define fi first
#define se second
#define mp make_pair
using namespace std;

typedef long long LL;
typedef pair<int, int> PII;

template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }

template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}

int n,m,fa[105];
int get(int x)
{
	return x==fa[x]?x:fa[x]=get(fa[x]);
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)fa[i]=i;
	for(int i=0;i<m;i++)
	{
		int a,b;
		scanf("%d%d",&a,&b);
		fa[get(a)]=get(b);
	}
	if(n!=m)puts("NO");
	else
	{
		int p=-1;
		for(int i=1;i<=n;i++)
			if(p==-1)p=get(i);
			else if(p!=get(i))
			{
				puts("NO");
				return 0;
			}
		puts("YES");
	}
	return 0;
}
posted @ 2022-01-29 21:52  zyy2001  阅读(53)  评论(0编辑  收藏  举报