我是靠谱客的博主 壮观百合,最近开发中收集的这篇文章主要介绍4216 图中的环(基环树),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

1. 问题描述:

给定一个 n 个点 m 条边的无向图。点的编号从 1 到 n。图中不含重边和自环。请你对给定图进行判断,如果该图是一个有且仅有一个环的连通图,则输出 YES,否则输出 NO。

输入格式

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

输出格式

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

数据范围

前三个测试点满足 1 ≤ n ≤ 10。
所有测试点满足 1 ≤ n ≤ 100,0 ≤ m ≤ 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
来源:https://www.acwing.com/problem/content/description/4219/

2. 思路分析:

首先我们需要分析一下满足题目要求的图有什么性质,可以发现首先需要连通,连通那么就一定存在一棵生成树,因为只有一个环所以这种图是环上挂着一堆树,由这个特点可以知道满足题目要求的这种图属于基环树,然后我们看一下基环树有什么特点,可以发现当一棵树是基环树的时候有两个特点:① 连通图;② m = n;并且当图满足特点①②的时候那么这种图属于基环树,所以这两个条件属于充分必要条件,因为当图连通的时候一定存在一棵生成树,而不管我们在生成树哪两个节点添加一条边最终都只有一个环,所以m = n,所以满足这两个特点的图是基环树;我们可以判断m是否等于n,如果m != n说明一定不是基环图,然后判断所有点是否在同一个集合中,判断所有点是否在同一个集合可以使用并查集进行判断:

3. 代码如下:

from typing import List


class Solution:
    # 并查集的find操作, 查找节点x的父节点, 查找节点的时候进行路径压缩
    def find(self, x: int, p: List[int]):
        if p[x] != x: p[x] = self.find(p[x], p)
        return p[x]

    def process(self):
        n, m = map(int, input().split())
        # n != m的时候说明不是基环图
        if n != m:
            print("NO")
            return
        # 使用并查集判断是否连通, p为并查集
        p = [i for i in range(n + 10)]
        res = n
        for i in range(m):
            a, b = map(int, input().split())
            fa, fb = self.find(a, p), self.find(b, p)
            # 当前两个点不在同一个集合那么合并这两个点
            if fa != fb:
                p[fa] = fb
                res -= 1
        # 说明所有点不是在同一个集合
        if res == 1:
            print("YES")
            return
        else:
            print("NO")
            return


if __name__ == '__main__':
    Solution().process()

最后

以上就是壮观百合为你收集整理的4216 图中的环(基环树)的全部内容,希望文章能够帮你解决4216 图中的环(基环树)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(48)

评论列表共有 0 条评论

立即
投稿
返回
顶部