Is it a tree?

本文探讨了如何通过树的定义来判断一组树枝是否能构成一棵树,并提供了相应的代码实现。通过查找根结点、路径压缩等算法,实现对树形结构的有效判断。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:

http://poj.org/problem?id=1308

大意:

给你一堆树枝,让你判断最后能不能构成一棵树。

思路:根据树的定义判断即可

树:

1.入度只能为1或者0(根结点)

2.根结点只有一个

3.出度可以有多个


代码如下:

#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> using namespace std; #define MAXN 10010 #pragma comment(linker, "/STACK:102400000,102400000") int pre[10010], son[10010], visit[10010]; int unionsearch(int root) //查找根结点+路径压缩(递归容易破栈) { int root2; root2 = root; while(root != pre[root]) root = pre[root]; while(root2 != root) { int temp = pre[root2]; pre[root2] = root; root2 = temp; } return root; } bool cmp() { int root = 0; for(int i = 0; i < MAXN; ++i) //累计根结点的子节点个数 if(visit[i]) ++son[unionsearch(i)]; for(int i = 0; i < MAXN; ++i) //累计根结点的个数 if(son[i] > 1) root++; if(root > 1) //判断为树或者为森林 return false; else return true; } int main() { //freopen("Input.txt", "r", stdin); int start, end, x, y, flag, T = 0; while(true) { flag = 0; for(int i = 0; i < MAXN; ++i) pre[i] = i; memset(son, 0, sizeof(son)); memset(visit, 0, sizeof(visit)); while(scanf("%d%d", &start, &end) && start && end) { if(start == -1 && end == -1) return 0; x = unionsearch(start); y = unionsearch(end); visit[start] = 1; // 树枝标记,忘了。调试了N久。 visit[end] = 1; if(x == y || end != y) //x == y为环,end == y,入度为2 flag = 1; else pre[end] = start; } if(flag) printf("Case %d is not a tree.\n", ++T); else { if(cmp()) printf("Case %d is a tree.\n", ++T); else printf("Case %d is not a tree.\n", ++T); } } return 0; }

改进后的程序(2011/10/25)

#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> using namespace std; #define MAXN 10010 int pre[10010], visit[10010]; int unionsearch(int root) //查找根结点+路径压缩 { int root2; root2 = root; while(root != pre[root]) root = pre[root]; while(root2 != root) { int temp = pre[root2]; pre[root2] = root; root2 = temp; } return root; } bool cmp() { int root = 0; for(int i = 0; i < MAXN; ++i) //累计根结点的子节点个数 if(visit[i] && pre[i] == i) root++; if(root > 1) //判断为树或者为森林 return false; else return true; } int main() { //freopen("Input.txt", "r", stdin); int start, end, x, y, flag, T = 0; while(true) { flag = 0; for(int i = 0; i < MAXN; ++i) pre[i] = i; memset(visit, 0, sizeof(visit)); while(scanf("%d%d", &start, &end) && start && end) { if(start == -1 && end == -1) return 0; x = unionsearch(start); y = unionsearch(end); visit[start] = 1; visit[end] = 1; if(x == y || end != y) flag = 1; else pre[end] = start; } if(flag) printf("Case %d is not a tree.\n", ++T); else { if(cmp()) printf("Case %d is a tree.\n", ++T); else printf("Case %d is not a tree.\n", ++T); } } return 0; }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值