目录

  • 《算法笔记》重点摘要
  • 1004 Counting Leaves (30)
  • 1053 Path of Equal Weight (30)
  • 1079 Total Sales of Supply Chain (25)
  • 1090 Highest Price in Supply Chain (25)
  • 1094 The Largest Generation (25)
  • 1106 Lowest Price in Supply Chain (25)

《算法笔记》 9.2 树的遍历 重点摘要

1. 常考边界条件

  • 空树:没有结点
  • 树只有一个根节点时,它亦为叶子结点

2. 树的静态实现

(1) 定义
  • 需要数据域
struct Node{
typename data;
int level;
vector<int> child;
} node[MAXN];
  • 不需要数据域,只需要树的结构
vector<int> child[MAXN];
(2) 新建结点
int index = 0;
int newNode (int value){
node[index].data = value;
node[index].child.clear();
return index++;
}
(3) 先根遍历
void preorder (int root){
printf("%d\n", node[root].data);
for (int i = 0; i < node[root].child.size(); i++)
preorder(node[root].child[i]);
}
(4) 层序遍历
void levelorder(int root){
queue<int> q;
q.push(root);
node[root].level = 0;
while(!q.empty()){
int front = q.front();
printf("%d ", node[front].data);
q.pop();
for (int i = 0; i < node[front].child.size(); i++){
int child = node[front].child[i];
node[child].level = node[front].level + 1;
q.push(node[front].child[i]);
}
}
}

3. 树与搜索

  • 合法的 DFS 遍历过程即树的先根遍历过程
  • 合法的 BFS 遍历过程即树的层序遍历过程

1004 Counting Leaves (30)

题目思路:DFS

  • 记录当前节点的层级和树的深度,当层级高于深度时,更新树的深度
  • 若当前节点为叶结点,对应层级的叶节点数 ++
  • 若非叶结点,递归进入其子结点
  • 最后依据树的深度输出各层级叶结点数
#include<iostream>
#include<vector>
using namespace std;
vector<int> children[100];
int levelnum[100] = {0}, depth = 1;
void dfs(int index, int level)
{
if (children[index].empty()){
levelnum[level]++;
if (level > depth) depth = level;
}
for (int i = 0; i < children[index].size(); i++)
dfs(children[index][i], level+1);
}
int main()
{
int n, m, id, k, child;
scanf("%d%d", &n, &m);
for (int i = 0; i < m; i++){
scanf("%d%d", &id, &k);
for (int j = 0; j < k; j++){
scanf("%d", &child);
children[id].push_back(child);
}
}
dfs(1,1);
printf("%d", levelnum[1]);
for (int i = 2; i <= depth; i++)
printf(" %d", levelnum[i]);
return 0;
}

1053 Path of Equal Weight (30)

题目思路:DFS

  • 由于要按权值输出,每接收完一个节点的子结点后就对其子结点容器进行排序,这样保证 DFS 时直接输出就是从大到小的顺序
  • 记录路径用 vector,访问子结点 进入下一层递归 DFS 前将其 push_back,从递归返回时再 pop_back,继续压入这一层下一个子结点
  • sum == weights 时,要判断当前节点的子结点容器是否为空,即是否是叶结点,若不是直接 return
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int weights;
vector<int> path;
struct Node{
int weight;
vector<int> children;
} node[100];
bool cmp (int a, int b){ return node[a].weight > node[b].weight; }
void DFS(int index, int sumweight)
{
if (sumweight > weights) return;
if (sumweight == weights){
if (!node[index].children.empty()) return;
for (int i = 1; i < path.size(); i++)
printf("%d ", node[path[i-1]].weight);
printf("%d\n", node[path[path.size()-1]].weight);
return;
}
for (int i = 0; i < node[index].children.size(); i++){
int child = node[index].children[i];
path.push_back(child);
DFS(child, sumweight+node[child].weight);
path.pop_back();
}
}
int main()
{
int n, m, id, k, child;
scanf("%d%d%d", &n, &m, &weights);
for (int i = 0; i < n; i++) scanf("%d", &node[i].weight);
for (int i = 0; i < m; i++){
scanf("%d%d", &id, &k);
for (int j = 0; j < k; j++){
scanf("%d", &child);
node[id].children.push_back(child);
}
sort(node[id].children.begin(), node[id].children.end(), cmp);
}
path.push_back(0);
DFS(0, node[0].weight);
return 0;
}

1079 Total Sales of Supply Chain (25)

题目思路:DFS

  • 树结点没有数据域,只要保存供应和售出的子结点关系,用 vector 的数组保存子结点即可
  • 用 map 保存零售商 id 与对应的货品数量,不需要顺序用 unordered_map 即可
  • DFS 用参数 index 和 level 标记当前遍历的结点的下标和层数
  • 若遇到叶结点,即子结点容器为空时,从 map 中取出对应的货品数量,根据层数计算单价,计算此零售商销售额后加入 sum 值中
  • 遍历结束后 sum 保存所求值,按要求输出即可
#include<iostream>
#include<vector>
#include<unordered_map>
#include<cmath>
using namespace std;
vector<int> children[100000];
double sum = 0, price, rate;
unordered_map<int,int> retailer;
void DFS(int index, int level){
if (children[index].empty())
sum += price * pow(1 + rate/100, level-1) * retailer[index];
for (int i = 0; i < children[index].size(); i++)
DFS(children[index][i], level+1);
}
int main()
{
int n, k, id, amount;
scanf("%d%lf%lf", &n, &price, &rate);
for (int i = 0; i < n; i++){
scanf("%d", &k);
if (!k) scanf("%d", &retailer[i]);
for (int j = 0; j < k; j++){
scanf("%d", &id);
children[i].push_back(id);
}
}
DFS(0,1);
printf("%.1f", sum);
return 0;
}

1090 Highest Price in Supply Chain (25)

题目思路

  • 树结点没有数据域,只要保存供应和售出的子结点关系,用 vector 的数组保存子结点即可
  • DFS 求树的最大深度和叶结点个数,按要求计算并输出
#include<iostream>
#include<vector>
#include<cmath>
using namespace std;
vector<int> children[100000];
int depth = 1, leafnum = 0;
void DFS(int index, int level){
if (level > depth){
depth = level;
leafnum = 1;
}
else if (level == depth) leafnum++;
for (int i = 0; i < children[index].size(); i++)
DFS(children[index][i], level+1);
}
int main()
{
int n, supplier, root;
double price, rate;
scanf("%d%lf%lf", &n, &price, &rate);
for (int i = 0; i < n; i++){
scanf("%d", &supplier);
if (supplier == -1) root = i;
else children[supplier].push_back(i);
}
DFS(root,1);
printf("%.2f %d\n", price * pow(1 + rate/100, depth-1), leafnum);
return 0;
}

1094 The Largest Generation (25)

BFS(层序遍历)

  • 要记录每层对应的结点数,在结点中设 level 变量记录层数,用 vector 记录子结点的下标
  • 层序遍历,每层将子结点压入队列时为子结点赋 level 值,弹出队列时给 level 值对应的数量 ++
  • 最后遍历记录每层结点数的 map,找到结点数最多的层输出
#include<iostream>
#include<unordered_map>
#include<queue>
using namespace std;
struct Node{
int level;
vector<int> children;
} node[100];
int main()
{
int n, m, id, k, child, root = 1, maxnum = 1, maxlevel = 1;
scanf("%d%d",&n,&m);
for (int i = 0; i < m; i++){
scanf("%d%d", &id, &k);
for (int j = 0; j < k; j++){
scanf("%d", &child);
node[id].children.push_back(child);
}
}
unordered_map<int,int> levelnum;
queue<int> q;
q.push(root);
node[root].level = 1;
while (!q.empty()){
int now = q.front();
levelnum[node[now].level]++;
q.pop();
for (int i = 0; i < node[now].children.size(); i++){
int child = node[now].children[i];
q.push(child);
node[child].level = node[now].level + 1;
}
}
for (auto it: levelnum){
if (it.second > maxnum){
maxnum = it.second;
maxlevel = it.first;
}
}
printf("%d %d\n", maxnum, maxlevel);
return 0;
}

DFS

  • 用参数 index 和 level 标记当前遍历的结点的下标和层数
  • 数组 levelnum 标记当前层数 level 所含结点数
  • 最后遍历一遍 levelnum 数组找出最大值。
#include<iostream>
#include<vector>
using namespace std;
vector<int> children[100];
int levelnum[100] = {0};
void dfs(int index, int level){
levelnum[level]++;
for (int i = 0; i < children[index].size(); i++)
dfs(children[index][i], level+1);
}
int main()
{
int n, m, id, k, child, maxnum = 1, maxlevel = 1;
scanf("%d%d",&n,&m);
for (int i = 0; i < m; i++){
scanf("%d%d", &id, &k);
for (int j = 0; j < k; j++){
scanf("%d", &child);
children[id].push_back(child);
}
}
dfs(1,1);
for (int i = 1; i < 100; i++){
if (levelnum[i] > maxnum){
maxnum = levelnum[i];
maxlevel = i;
}
}
printf("%d %d\n", maxnum, maxlevel);
return 0;
}

1106 Lowest Price in Supply Chain (25)

题目思路:DFS

  • 保存最小叶结点的深度 depth,对应深度的叶结点个数 leafnum
  • DFS 遇到叶结点与 depth 比较,若相等将个数 ++,若小于 depth 说明找到了更小的深度,更新 depth,重置 leafnum = 1
#include<iostream>
#include<vector>
#include<cmath>
using namespace std;
vector<int> children[100000];
int depth = 100000;
int leafnum = 0;
void DFS(int index, int level)
{
if (children[index].empty()){
if (level == depth) leafnum++;
else if (level < depth){
depth = level;
leafnum = 1;
}
}
for (int i = 0; i < children[index].size(); i++)
DFS(children[index][i], level+1);
}
int main()
{
int n, k, child;
double price, rate;
scanf("%d%lf%lf", &n, &price, &rate);
for (int i = 0; i < n; i++){
scanf("%d", &k);
for (int j = 0; j < k; j++){
scanf("%d", &child);
children[i].push_back(child);
}
}
DFS(0,1);
printf("%.4f %d", price * pow(1 + rate/100, depth-1), leafnum);
return 0;
}

PAT甲级 树 相关题_C++题解的更多相关文章

  1. PAT甲级 二叉树 相关题_C++题解

    二叉树 PAT (Advanced Level) Practice 二叉树 相关题 目录 <算法笔记> 重点摘要 1020 Tree Traversals (25) 1086 Tree T ...

  2. PAT甲级 二叉查找树 相关题_C++题解

    二叉查找树 PAT (Advanced Level) Practice 二叉查找树 相关题 目录 <算法笔记> 重点摘要 1099 Build A Binary Search Tree ( ...

  3. PAT甲级 Dijkstra 相关题_C++题解

    Dijkstra PAT (Advanced Level) Practice Dijkstra 相关题 目录 <算法笔记>重点摘要 1003 Emergency (25) <算法笔记 ...

  4. PAT甲级 图 相关题_C++题解

    图 PAT (Advanced Level) Practice 用到图的存储方式,但没有用到图的算法的题目 目录 1122 Hamiltonian Cycle (25) 1126 Eulerian P ...

  5. PAT甲级 堆 相关题_C++题解

    堆 目录 <算法笔记>重点摘要 1147 Heaps (30) 1155 Heap Paths (30) <算法笔记> 9.7 堆 重点摘要 1. 定义 堆是完全二叉树,树中每 ...

  6. PAT甲级 散列题_C++题解

    散列 PAT (Advanced Level) Practice 散列题 目录 <算法笔记> 重点摘要 1002 A+B for Polynomials (25) 1009 Product ...

  7. PAT甲级 字符串处理题_C++题解

    字符串处理题 目录 <算法笔记> 重点摘要 1001 A+B Format (20) 1005 Spell It Right (20) 1108 Finding Average (20) ...

  8. PAT甲级 并查集 相关题_C++题解

    并查集 PAT (Advanced Level) Practice 并查集 相关题 <算法笔记> 重点摘要 1034 Head of a Gang (30) 1107 Social Clu ...

  9. PAT甲级 图的遍历 相关题_C++题解

    图的遍历 PAT (Advanced Level) Practice 图的遍历 相关题 目录 <算法笔记>重点摘要 1021 Deepest Root (25) 1076 Forwards ...

随机推荐

  1. SpringMVC 捕获参数绑定失败时的异常

    SpringMVC配置数据验证(JSR-303)中提到了用String类型的域来绑定Ajax中的非法类型的参数. 这样做的目的是一旦发生一种情况,后端可以返回一个自定类的返回值,而不是返回Spring ...

  2. zabbix (二)安装

    一.centos7源码安装zabbix3.x 1.安装前环境搭建 下载最新的yum源 #wget -P /etc/yum.repos.d http://mirrors.aliyun.com/repo/ ...

  3. python3编程基础之一:代码封装

    几乎现代的编程语言都支持函数,函数是代码段的封装,并能实现一特定功能,并能重复使用的代码单位.之前的pow()和sqrt()和print()和input()等类似的内置函数,就是python内部已经实 ...

  4. GO- 使用JSON

    1 json.Marshal  把对象转换为JSON的方法 原型如下 func Marshal(v interface{}) ([]byte, error)这个函数接收任意类型的数据 v,并转换为字节 ...

  5. 基于Python的GMSSL实现

    基于Python的GMSSL实现 团队任务 一.小组讨论对课程设计任务的理解 基于Python的GMSSL实现,即GmSSL开源加密包的python实现,支持其SM2/SM3/SM4等国密(国家商用密 ...

  6. legend3---19、要更多的从服务器端控制元素的显示和隐藏,而不要是页面端

    legend3---19.要更多的从服务器端控制元素的显示和隐藏,而不要是页面端 一.总结 一句话总结: 这样可以控制很多页面端的非法操作 1.html标签中data方式的数据,修改之后在标签上只显示 ...

  7. Java同步数据结构之ConcurrentSkipListMap/ConcurrentSkipListSet

    引言 上一篇Java同步数据结构之Map概述及ConcurrentSkipListMap原理已经将ConcurrentSkipListMap的原理大致搞清楚了,它是一种有序的能够实现高效插入,删除,更 ...

  8. PAT 甲级 1041 Be Unique (20 分)(简单,一遍过)

    1041 Be Unique (20 分)   Being unique is so important to people on Mars that even their lottery is de ...

  9. scdbg分析shellcode

    https://isc.sans.edu/forums/diary/Another+quickie+Using+scdbg+to+analyze+shellcode/24058/ scdbg -f s ...

  10. 100道iOS面试题

    面试题: 1__weak什么时候用 想要在block内部变外部变量需要加__weak或者__block 2.是否使用过coreImage和coreText?如果使用过,说说你的体验(答案在另一份) 3 ...