261. 以图判树(中等)
Blind 75 › 261. 以图判树(中等) (第 5 章)
题目
有 n 个节点,编号从 0 到 n-1;再给一组无向边 edges,每条边连接两个不同节点。判断这些边是否恰好构成一棵树。
一棵树必须同时满足两个条件:连通(任意两节点都可达)且无环(任意两节点之间的简单路径唯一)。
自造示例:
n = 6, edges = [[0,1],[0,2],[1,3],[1,4],[2,5]]→true。整张图连通,5 条边正好把 6 个节点连成一棵树。n = 4, edges = [[0,1],[1,2],[2,0]]→false。节点 0、1、2 成环,节点 3 孤立:既不无环,也不连通。n = 4, edges = [[0,1],[2,3]]→false。没有环,但两个连通块彼此不连通。
约束:1 ≤ n ≤ 2000;0 ≤ edges.length ≤ 5000;每条边为 [a,b],满足 0 ≤ a,b ≤ n−1 且 a ≠ b。
思路
一句话:树 = 连通 + 无环,用一次带 parent 的 DFS/BFS 同时检查这两个条件。
最直白的做法:从每个未访问节点出发跑一遍遍历,统计连通块;再单独跑一遍环检测。这个思路正确,但要维护两套逻辑,还可能把“沿父节点原路返回”误判成环。
关键观察一:无向图 DFS 中,如果遇到一个已访问且不是父节点的邻居,说明从当前点绕了一圈回来,必定有环。因此只要在 DFS 中带上 parent,一次遍历就能判环。
关键观察二:从 0 号点出发的一次 DFS,会把与 0 相连的整块都标记为已访问。最后若还有节点没被访问,就说明图不连通。
再加一个廉价剪枝:n 个节点的树必然只有 n−1 条边。边数不是 n−1,直接 false;边数是 n−1 时,再用一次遍历验证“无环 + 全连通”。
解法
整体步骤:建邻接表 → 检查边数 → 带 parent 的 DFS 判环 → 检查是否所有节点都被访问。
| 输入 | 边数检查 | DFS 发现 | 是否全访问 | 结果 |
|---|---|---|---|---|
| 6 节点树形示例 | 5 == 6−1 | 无环 | 是 | true |
| 三角 + 孤立点 | 3 == 4−1 | 0-1-2 成环 | 否 | false |
| 两个连通块 | 2 != 4−1 | 不进入 DFS | — | false |
第三个例子说明:边数检查能提前拦下一部分错误答案,但它只是必要条件,不能替代遍历。
下图把上面 4 个步骤串成流程,并逐步演示:


C++
class Solution {
public:
bool validTree(int n, vector<vector<int>>& edges) {
if (n == 0) return true;
if ((int)edges.size() != n - 1) return false; vector<vector<int>> adj(n);
for (auto& e : edges) {
adj[e[0]].push_bac本篇为付费内容
您已阅读试读部分,购买后即可解锁全文。
⚠️ 本站内容已做唯一性标记并受版权保护,未经授权禁止转载,侵权必究。
还没有评论,来说两句?