1053 Path of Equal Weight (30分)
题目链接:PAT A 1053
题目大意:输入第一行给出三个数n,m,s,分别代表树的结点个数,非叶结点个数,以及重量。接下来一行给出每个结点的的重量,接下来m行给出每个非叶结点的子结点。题目要求我们找出所有从根结点出发到叶结点的路径中,有哪些重量之和等于s。要求找出它们并按照序列递减的顺序输出。
思路分析:对于一棵树,我们通常用如下结构来表示它:
struct Node{
int data; //数据域
vector<int> child; //孩子结点
}
先按照题目输入,构造出一棵树,由于题目最后要求按照重量序列递减的顺序输出,所以我们在输入完每一个结点的所有子结点后要对这些子结点按照重量由大到小的顺序排序。这样在遍历时就会优先遍历到重量大的子结点。定义一个int类型的path数组用来记录路径,初始时path[0]赋值为0。之后开始编写dfs类型函数preorder,定义变量index表示当前访问的结点的索引,变量numnode代表递归层数,变量sum代表重量值累计之和。每次进入preorder函数,先判断sum是否大于s,如果大于则直接返回,如果sum与s相等,首先判断该节点是不是叶子结点(题目要求的是从根结点到叶子结点的路径),如果不是则返回,如果是就结合路径进行输出。对于每个结点的所有子结点进行递归访问,访问的过程中改变sum的值,具体可结合代码来进行理解。
AC代码:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int n, m, s, path[105];
struct Node{
int weight; //结点重量
vector<int> child; //孩子结点
}node[105];
void preorder(int index, int numnode, int sum) {
if(sum > s)
return;
else if(sum == s) {
if(node[index].child.size() != 0) //不是叶结点
return;
for(int i = 0; i < numnode; i++) {
printf("%d", node[path[i]].weight);
if(i != numnode - 1)
printf(" ");
else
printf("\n");
}
}
for(int i = 0; i < node[index].child.size(); i++) {
int child = node[index].child[i];
path[numnode] = child; //更新路径
preorder(child, numnode + 1, sum + node[child].weight); //递归
}
}
bool cmp(int a, int b) {
return node[a].weight > node[b].weight;
}
int main() {
int nonleaf, k, temp;
scanf("%d %d %d", &n, &m, &s);
for(int i = 0; i < n; i++)
scanf("%d", &node[i].weight);
for(int i = 0; i < m; i++) {
scanf("%d %d", &nonleaf, &k);
for(int j = 0; j < k; j++) {
scanf("%d", &temp);
node[nonleaf].child.push_back(temp);
}
sort(node[nonleaf].child.begin(), node[nonleaf].child.end(), cmp); //排序便于输出
}
path[0] = 0; //根节点的索引是0
preorder(0, 1, node[0].weight);
return 0;
}