LA3902树形网络递归

本文介绍了如何解决一个涉及网络结构的题目,该题目要求在无环图中,从指定server出发找到k距离内的叶子节点。通过将无根树转化为有根树,从最深叶子节点向上找到k个祖先作为server,以此实现最优解。文章提供了DFS的代码实现,讨论了邻接链表的构建和避免死循环的方法。

经典题,需要温习。

题目链接:点击这里

总体思路

  1. 此题是网络结构,好久没做过这种题了。需要注意的是,这里有n个点,只有n-1条边,一定是无环图。因此,此题是无根树。
  2. 处理无根树比较麻烦,我们只知道一台server的编号,可以从这个server出发进行DFS,找到在其k距离范围内能达到的叶子节点(client)。但接下来怎么做呢?如何找到剩余叶子节点的最小server数呢?
  3. 因此,可以将无根树转化为有根数,就把server当作根节点,第一次DFS找到可以到达的所有叶子节点,然后从深度最深的叶子节点出发,找到其k祖先,将其设置为server,很容易证明这样是最省的。

代码实现

  • 思路不是很难想,但代码上需要有些技巧。

树的构建

  • 我们知道,可以使用邻接矩阵来构建,但在无向图中太浪费空间,并且此题n最大可以去1000,会造成内存溢出。
  • 因此我们可以采用邻接链表的形式,由于此题只有编号没有其他信息,因此可构建树vector<int> nodes[maxn];
  • 如何快速的找到其k个祖先呢?这里使用了一个数组进行存储其父节点,需要注意的是,由于此题是无向图,因此要注意方向,不然会造成死循环。

示例代码

  • 由于深度不超过k的叶子节点已经被服务器覆盖了,因此我们存储深度的时候,只存储深度大于k的节点,使用DFS来覆盖。

    
    #include <iostream><
### 广义表的长度和深度计算 #### 长度计算 广义表的长度是指该表中顶层元素的数量。对于给定的广义表 \( LA = ((), a, (b, c), d, (e, f, g)) \),它的长度可以通过统计顶层括号内的独立子项数量来得到。在这个例子中,\( LA \) 的顶层元素有五个:\(\emptyset\)、\(a\)、\((b, c)\)、\(d\) 和 \((e, f, g)\)。因此,广义表 \( LA \) 的长度为 5。 #### 深度计算 广义表的深度定义为其嵌套的最大层数。为了计算深度,可以采用递归的方式逐层深入直到遇到原子(非列表形式的数据)。对于广义表 \( LA = ((), a, (b, c), d, (e, f, g)) \): - 子表 \(()\) 的深度为 1。 - 子表 \((b, c)\) 的深度为 2(因为 \(b\) 和 \(c\) 是原子)。 - 子表 \((e, f, g)\) 的深度同样为 2。 综合以上分析可知,整个广义表 \( LA \) 的最大嵌套层次数为 2,所以其深度为 2[^1]。 ### C++ 实现提取字符 'f' 以下是基于 C++ 编程语言的一个简单实现方案,用于从指定的广义表中找到并返回字符 'f': ```cpp #include <iostream> #include <vector> using namespace std; // 定义节点结构体表示广义表中的每一个单元 struct GListNode { bool isAtom; union { char atomValue; // 如果是原子,则存储对应的值 vector<GListNode*> subList; // 如果是非原子,则指向另一个广义表 }; }; // 创建广义表的方法简化版省略具体细节... void findCharF(GListNode* node){ if(node->isAtom && node->atomValue == 'f'){ cout << "Found character 'f'" << endl; return ; } if(!node->isAtom){ // 若当前节点是一个子表而非单个字母 for(auto child : node->subList){ findCharF(child); } } } int main(){ // 初始化广义表 LA=((),a,(b,c),d,(e,f,g)) // 这里仅展示逻辑框架,实际初始化过程需更详尽代码构建完整的树形数据结构 GListNode* root = new GListNode(); // 构建各部分...此处假设已完成创建root代表整个广义表... // 调用函数寻找字符‘f’ findCharF(root); return 0; } ``` 此程序片段展示了如何通过递归访问广义表的不同层级直至发现目标字符 ‘f’。注意这只是一个概念性的演示,在真实应用时可能还需要考虑内存管理等问题以确保程序健壮性和效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值