1 条题解
-
0
这段代码实现了判断一个图是否为**毛毛虫树(Caterpillar Tree)**的算法。毛毛虫树是一种特殊的树,其结构可以抽象为一条主干路径(脊椎),所有叶子节点(度数为1的节点)直接连接到这条路径上。
算法原理
毛毛虫树的定义:
毛毛虫树是一棵树,且满足:所有非叶子节点(度数≥2)构成一条简单路径(称为脊椎),所有叶子节点直接连接到这条路径上。判断策略:
必要条件:输入图必须是一棵树(即连通且边数为n-1)。
核心思想:从任意一个非叶子节点出发进行DFS,尝试遍历所有非叶子节点形成的路径,并标记所有可达的叶子节点。若所有节点都被标记,则该树是毛毛虫树。DFS遍历规则:
当遍历到一个非叶子节点时,若其度数≥3,则停止继续深入(因为脊椎路径上的节点度数最多为2,度数≥3的节点会导致路径分叉)。
若遇到叶子节点(度数为1),直接标记该节点但不继续递归。关键步骤
预处理:
输入图必须是树(边数为n-1),否则直接判定不是毛毛虫树。DFS遍历:
从任意一个非叶子节点出发,递归遍历所有非叶子节点,并标记遇到的叶子节点。
若DFS过程中某个节点的度数≥3,停止从该节点继续深入,避免遍历到非脊椎路径。结果检查:
若所有节点都被DFS标记,则该树是毛毛虫树;否则不是。总结
该算法通过DFS遍历脊椎路径并验证所有叶子节点的连接性,高效判断一个树是否为毛毛虫树。其核心在于利用脊椎路径的线性结构特性,确保所有非叶子节点形成一条简单路径。
#include<iostream> #include <cstring> // 引入 memset #include <cstdio> // 引入 scanf 和 printf using namespace std; const int maxN = 128; int g[maxN][maxN]; int d[maxN], ok[maxN], vis[maxN]; int n; void dfs(int u) { int v, cnt = 0; ok[u] = 1; vis[u] = 1; for (v = 1; v <= n; ++v) if (g[u][v] == 1 && d[v] > 1) { ++cnt; if (cnt == 3) return; } for (v = 1; v <= n; ++v) if (g[u][v] == 1 && vis[v] == 0) { if (d[v] == 1) { ok[v] = 1; continue; } else dfs(v); } } int main() { int cases = 0; while (scanf("%d", &n) == 1 && n) { // 使用 scanf 读取输入 int m; memset(g, 0, sizeof(g)); memset(d, 0, sizeof(d)); memset(ok, 0, sizeof(ok)); memset(vis, 0, sizeof(vis)); scanf("%d", &m); // 读取边数 for (int i = 0; i < m; ++i) { int a, b; scanf("%d%d", &a, &b); // 读取边的两个顶点 g[a][b] = g[b][a] = 1; ++d[a]; ++d[b]; } if (m != n - 1) { // 非树结构直接判断 printf("Graph %d is not a caterpillar.\n", ++cases); // 使用 printf 输出 continue; } int i, flag = 0; for (i = 1; i <= n; ++i) if (d[i] > 1) break; // 找到第一个度数大于1的节点 dfs(i); // 从该节点开始DFS for (i = 1; i <= n; ++i) if (ok[i] != 1) // 检查所有节点是否被标记 flag = 1; if (flag == 1) printf("Graph %d is not a caterpillar.\n", ++cases); else printf("Graph %d is a caterpillar.\n", ++cases); } return 0; }
- 1
信息
- ID
- 2311
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 5
- 标签
- 递交数
- 2
- 已通过
- 1
- 上传者