一个无向图是树的条件是:
- 它没有环
- 它是连通的
我们可以用深度优先搜索(DFS)来检测这两个条件。下面是演示的代码实现:
#include <iostream>
#include <vector>
using namespace std;
// 用邻接矩阵表示无向图
class Graph {
int V; // 顶点数
vector<vector<int>> adj; // 邻接矩阵
bool isCyclicUtil(int v, vector<bool>& visited, int parent); // 辅助函数,用DFS检测是否有环
public:
Graph(int V); // 构造函数
void addEdge(int v, int w); // 添加一条边
bool isTree(); // 判断是否为树
};
Graph::Graph(int V) {
this->V = V;
adj = vector<vector<int>>(V, vector<int>(V, 0)); // 初始化邻接矩阵为全0
}
void Graph::addEdge(int v, int w) {
adj[v][w] = 1; // 设置邻接矩阵中对应的元素为1,表示有边相连
adj[w][v] = 1;
}
bool Graph::isCyclicUtil(int v, vector<bool>& visited, int parent) {
visited[v] = true; // 标记当前顶点为已访问
for (int i = 0; i < V; i++) { // 遍历邻接矩阵的一行,找到与当前顶点相连的顶点
if (adj[v][i] == 1) { // 如果有边相连
if (!visited[i]) { // 如果该顶点未访问过,递归检测是否有环
if (isCyclicUtil(i, visited, v)) return true;
}
else if (i != parent) return true; // 如果该顶点已访问过,并且不是当前顶点的父节点,说明有环
}
}
return false; // 没有找到环,返回false
}
bool Graph::isTree() {
vector<bool> visited(V, false); // 初始化一个布尔数组,记录每个顶点是否被访问过
if (isCyclicUtil(0, visited, -1)) return false; // 从任意一个顶点开始,用DFS检测是否有环,如果有,返回false
for (int i = 0; i < V; i++) { // 检查是否所有顶点都被访问过,如果没有,说明不是连通的,返回false
if (!visited[i]) return false;
}
return true; // 没有环且连通,返回true
}
int main() {
Graph g1(5); // 创建一个有5个顶点的图
g1.addEdge(0, 1); // 添加边
g1.addEdge(0, 2);
g1.addEdge(0, 3);
g1.addEdge(3, 4);
g1.isTree() ? cout << "g1是树\n" : cout << "g1不是树\n"; // 判断是否为树
Graph g2(5); // 创建另一个有5个顶点的图
g2.addEdge(0, 1);
g2.addEdge(0, 2);
g2.addEdge(2, 3);
g2.addEdge(2, 4);
g2.addEdge(3, 4);
g2.isTree() ? cout << "g2是树\n" : cout << "g2不是树\n"; // 判断是否为树
return 0;
}
输出结果:
g1是树
g2不是树
参考链接
(1)Check if a given graph is tree or not - GeeksforGeeks
(2)Determining Whether a Directed or Undirected Graph Is a Tree
(3)Determining whether or not a directed or undirected graph is a tree
(4)How to determine if a given directed graph is a tree