Given n nodes labeled from 0 to n - 1 and a list of undirected edges (each edge is a pair of nodes), write a function to check whether these edges make up a valid tree.
For example:
Given n = 5 and edges = [[0, 1], [0, 2], [0, 3], [1, 4]], return true.
Given n = 5 and edges = [[0, 1], [1, 2], [2, 3], [1, 3], [1, 4]], return false.
Hint:
Given n = 5 and edges = [[0, 1], [1, 2], [3, 4]], what should your return? Is this case a valid tree?
According to the definition of tree on Wikipedia: “a tree is an undirected graph in which any two vertices are connected by exactly one path. In other words, any connected graph without simple cycles is a tree.”
根据维基百科,一个树必定是一个图,那么判断一个图是否是一个树,应该满足两点
- 是一个全连通图(所有节点相通)
- 无回路
- 图的边数=节点数-1
2和3 等价
DFS
思路:首先对所有边进行遍历,把连通的加入结果中,然后再对结果进行dfs,直到所有的边遍历完,并且没有重复的边出现时,返回true。
bool validTree(int n,vector<pair<int,int>>& edges){
vector<vector<int>> g(n,vector<int>());//一个二维变量用来存储所有边的连通情况
unordered_set res{
{
0}};//用来存放结果,如果从起始点到该点连通则加入,最后判断是否为n的大小
queue<int> que{
{
0}};//用来dfs的队列
//初始化g
for(auto edge:edges){
g[edge.first].insert(g[edge.second]);
g[edge.second].insert(g[edge.first]);
}
while(!que.empty()){
int cur=que.front();
que.pop();
for(auto vex:g[cur]){
if(res.count(cur)) return false;//环路
que.push(vex);
res.insert(vex);
g[vex].erase(cur);//在对称处删除
}
}
return res.size==n;
}
BFS
思路:广度优先遍历是所有边走一遍,删除掉重复边,再进行遍历判断是否存在环路
深度优先遍历是一个点走到底再递归
设置一个和顶点数目相同的visited数组,判断当前顶点是否已经加入结果
一个二维数组初始化边集
bool validTree(int n,vector<pair<int,int>>& edges){
vector<vector<int>> g(n,vector<int>());
vector<bool> visited(n,false);
if(!dfs(g,visited,0,-1)) return false;
for(auto b:visited){
if(!b) return false;
}
}
bool dfs(vector<vector<int>>& g,vector<bool>& visited,int cur,int pre){
if(visited(cur)) return false;//首先判断是否已经加入结果
visited(cur)=true;
for(auto vex:g[cur]){
//对该点连通的点进行遍历
if(vex!=pre){
if(!dfs(g,visited,vex,cur)) return false;
}
}
}