(PAT Advanced)1053.Path of Equal Weight (树的遍历) C++

原题:https://pintia.cn/problem-sets/994805342720868352/problems/994805424153280512

题目描述
Sample Input:
20 9 24
10 2 4 3 5 10 2 18 9 7 2 2 1 3 12 1 8 6 2 2
00 4 01 02 03 04
02 1 05
04 2 06 07
03 3 11 12 13
06 1 09
07 2 08 10
16 1 15
13 3 14 16 17
17 2 18 19

Sample Output:
10 5 2 7
10 4 10
10 3 3 6 2
10 3 3 6 2

题目大意

给出树的结构和树上结点的权重,找到从根结点到叶子节点上权重相加等于给定目标数的路径,并按照权重从到到小输入路径。

题目分析

找到权重为某一值的路径,从根结点进行深度优先遍历(DFS)到叶子结点的时候判断权重总值是否符合要求即可。但是按照非降序输入,类似于字符串比较间的字典序,需要依次比较路径结点的权值,所以,为了方便,我们可以在输入完一个结点的孩子结点后,就对其孩子结点按照权重从大到小排序,让权重大的在前面,最后进行DFS后的结果就是符合条件的。

/* 1053 Path of Equal Weight (30 分) */
// 使用链表或者多维向量存储图
// 使用深度优先遍历找路径的长度
// 可以先将子节点按照权重进行排序,这样DFS后就是非升序
#include<vector>
#include<algorithm>
#include<iostream>

using namespace std;

const int MAXNUM = 100;  // 最大结点数目
int weight[MAXNUM];
vector<vector<int> > map(MAXNUM); // 邻接表
vector<int> path; // 结果路径
int n, m, s;

int cmp(int a, int b) {
	return weight[a] > weight[b];
}
void dfs(int node,int dis) {
	dis += weight[node];
	if (dis > s) return; // 权重超出范围
	path.push_back(node);
	if (map[node].size() == 0) { // 叶子结点
		if (dis == s) {
			for (int i = 0; i < path.size(); i++) {
				printf("%d%c", weight[path[i]], i == path.size() - 1 ? '\n' : ' ');
			}
		}
	}
	else { // dfs孩子结点
		for (int i = 0; i < map[node].size(); i++) dfs(map[node][i], dis);
	}
	path.pop_back();
}
int main() {
	scanf("%d %d %d", &n, &m, &s);
	map.resize(n);
	for (int i = 0; i < n; i++) scanf("%d", &weight[i]);
	int node, cnt, child;
	for (int i = 0; i < m; i++) {
		scanf("%d %d", &node, &cnt);
		for (int j = 0; j < cnt; j++) {
			scanf("%d", &child);
			map[node].push_back(child);
		}
		// 先进行排序,大权重在前
		sort(map[node].begin(), map[node].end(), cmp);
	}
	// 深度优先搜索找路径
	dfs(0,0);

	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,您的四个问题我都可以回答。请看下面的解释: 1. 统计二叉的叶结点个数 答:统计二叉的叶结点个数可以采用递归的方式。如果二叉为空,则叶节点个数为0,如果二叉不为空且左右子均为空,则当前节点为叶节点,个数为1,否则叶节点个数等于左子的叶节点个数加右子的叶节点个数。 代码实现: int CountLeaf(Node *root) { if(root == NULL) return 0; if(root->left == NULL && root->right == NULL) return 1; return CountLeaf(root->left) + CountLeaf(root->right); } 2. 判别两棵是否相等 答:判别两棵是否相等也可以采用递归的方式。若两棵均为空,则它们相等。如果两棵都不为空,那么如果它们的根结点值相等,且左子和右子分别相等,则两棵相等。 代码实现: bool IsEqual(Node *root1, Node *root2) { if(root1 == NULL && root2 == NULL) return true; if(root1 != NULL && root2 != NULL) { if(root1->value == root2->value && IsEqual(root1->left, root2->left) && IsEqual(root1->right, root2->right)) return true; } return false; } 3. 交换二叉每个结点的左孩子和右孩子 答:交换二叉每个结点的左孩子和右孩子同样可以采用递归的方式。如果当前节点不为空,则交换当前节点的左孩子和右孩子,然后递归处理左子和右子。 代码实现: void Mirror(Node *root) { if(root == NULL) return; Node *temp = root->left; root->left = root->right; root->right = temp; Mirror(root->left); Mirror(root->right); } 4. 设计二叉的双序遍历算法 答:双序遍历算法可以同时遍历二叉的前序序列和后序序列。在遍历前序序列的同时,记录当前节点在后序序列中的位置。对于每个节点,先输出其前序值,然后判断其左子和右子在后序序列中出现的位置关系,进而输出其后序值。具体实现过程如下: void DoubleOrder(Node *root, int pre[], int post[], int &pre_index, int &post_index) { if(root == NULL) return; // 输出前序值 cout << root->value << " "; pre[pre_index++] = root->value; if(root->left != NULL) DoubleOrder(root->left, pre, post, pre_index, post_index); if(root->right != NULL) DoubleOrder(root->right, pre, post, pre_index, post_index); // 判断左右子是否为空 if(root->left == NULL && root->right == NULL) return; // 输出后序值 while(post_index >= 0 && post[post_index] != root->left->value && post[post_index] != root->right->value) cout << post[post_index--] << " "; if(post[post_index] == root->left->value) DoubleOrder(root->left, pre, post, pre_index, post_index); if(post[post_index] == root->right->value) DoubleOrder(root->right, pre, post, pre_index, post_index); cout << root->value << " "; } 其中,pre和post分别为前序序列和后序序列的数组,pre_index和post_index分别指向当前节点在前序序列和后序序列中的位置。在输出后序值时,需要根据当前节点的左右子在后序序列中的位置来决定先输出哪个子的后序值,这里可以采用一个while循环来处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值