PAT甲级 树 相关题_C++题解
树
目录
- 《算法笔记》重点摘要
- 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++题解的更多相关文章
- PAT甲级 二叉树 相关题_C++题解
二叉树 PAT (Advanced Level) Practice 二叉树 相关题 目录 <算法笔记> 重点摘要 1020 Tree Traversals (25) 1086 Tree T ...
- PAT甲级 二叉查找树 相关题_C++题解
二叉查找树 PAT (Advanced Level) Practice 二叉查找树 相关题 目录 <算法笔记> 重点摘要 1099 Build A Binary Search Tree ( ...
- PAT甲级 Dijkstra 相关题_C++题解
Dijkstra PAT (Advanced Level) Practice Dijkstra 相关题 目录 <算法笔记>重点摘要 1003 Emergency (25) <算法笔记 ...
- PAT甲级 图 相关题_C++题解
图 PAT (Advanced Level) Practice 用到图的存储方式,但没有用到图的算法的题目 目录 1122 Hamiltonian Cycle (25) 1126 Eulerian P ...
- PAT甲级 堆 相关题_C++题解
堆 目录 <算法笔记>重点摘要 1147 Heaps (30) 1155 Heap Paths (30) <算法笔记> 9.7 堆 重点摘要 1. 定义 堆是完全二叉树,树中每 ...
- PAT甲级 散列题_C++题解
散列 PAT (Advanced Level) Practice 散列题 目录 <算法笔记> 重点摘要 1002 A+B for Polynomials (25) 1009 Product ...
- PAT甲级 字符串处理题_C++题解
字符串处理题 目录 <算法笔记> 重点摘要 1001 A+B Format (20) 1005 Spell It Right (20) 1108 Finding Average (20) ...
- PAT甲级 并查集 相关题_C++题解
并查集 PAT (Advanced Level) Practice 并查集 相关题 <算法笔记> 重点摘要 1034 Head of a Gang (30) 1107 Social Clu ...
- PAT甲级 图的遍历 相关题_C++题解
图的遍历 PAT (Advanced Level) Practice 图的遍历 相关题 目录 <算法笔记>重点摘要 1021 Deepest Root (25) 1076 Forwards ...
随机推荐
- Fidller抓包分析post请求
目的:抓包是为了最近做接口测试做准备,以前没有用过这个工具,最近来学下,但是网上很多文章了,所以不一一记录,有一部分参考即可 1.如何抓取想要的web端或者手机端包,已经有很多文章谢了,推荐的参考文章 ...
- linux 查看某个进程内存占用情况命令
1.先用ps查询进程号 ps -aux|grep 进程名字 2.查看更详细的内存占比 cat /proc/3664/status 返回结果:(其中VmRSS为进程所占用的内存)
- 走进JavaWeb技术世界10:从JavaBean讲到Spring
Java 帝国之Java bean (上) 转自: 刘欣 码农翻身 2016-05-27 前言: 最近看到到spring 的bean 配置, 突然想到可能很多人不一定知道这个叫bean的东西的来龙去脉 ...
- linux下 安装 ImageMagick 及其 php imagick扩展(转)
linux下 安装 ImageMagick 及其 php imagick扩展 PHP版本7.1.3 : ImageMagick版本 ImageMagick-7.0.8-3: PHP扩展imagick版 ...
- Hallelujah Leonard Cohen
Hallelujah 歌词 Leonard Cohen Now I've heard there was a secret chord 我听说有一个隐秘的弦音 That David ...
- Ubuntu16.04 + cuda9.0 +cudnn7.1(转载)
转载一个详细可用的ubuntu16.04+cuda9.0+cudnn7.1教程. 0 - 参考材料 https://blog.csdn.net/Umi_you/article/details/8026 ...
- mouse without borders无界鼠标使用教程
mouse without borders无界鼠标使用教程 摘自https://www.jianshu.com/p/6a0209ad03f8 老黑随笔 关注 0.4 2018.05.18 11: ...
- laravel容器类make方法解释
容器类调用make方法时,如果没有已注册的key,那么会自动通过反射类实例化具体类 make /** * Resolve the given type from the container. * * ...
- Hibernatne 缓存中二级缓存简单介绍
hibernate的session提供了一级缓存,每个session,对同一个id进行两次load,不会发送两条sql给数据库,但是session关闭的时候,一级缓存就失效了. 二级缓存是Sessio ...
- Docker Swarm 集群(十七)
目录 一.Docker Swarm 概念 1.集群 2.Docker Swarm 3.重要概念 swarm node service 二.创建 Swarm 集群 1.环境准备 2.创建 swarm 3 ...