题目大意:
给定一颗树和每个结点的权值,求从所有根结点到叶子结点的路径,使得每条路径上的权值之和等于给定的常数S.如果有多条路径,按照路径的非递增序列输出
算法思路:
考察树的遍历,由于需要求从所有根结点到叶子结点的路径,很自然就想到使用先序遍历该树,并且使用$path$保存当前搜索路径,$result$保存所有符合条件的路径,如果当前结点是叶子结点,那么就先将此结点添加到$path$中,然后再计算$path$总所有结点的总权重,如果和给定的S相等,那么就将$path$添加进$result$中。接着得回退,先将叶子结点退出$path$,然后再返回。如果当期结点不是叶子结点,那么就先将当前结点添加进$path$中,然后再递归遍历其每一个孩子结点,在每一个孩子都遍历完毕后就将当期结点退出$path$,这样就完成了整个树的搜索过程。搜索结束后,$result$就保存了所有满足条件的路径,接着就是将$result$的每一条路径序列按照字典序从大到小排序,最后再输出即可。
注意点:
- 1、在不排序的情况下,可以获得10分,测试点0和2错误。
- 2、测试点2的错误和测试点5的段错误均是因为排序函数的问题,首先得注意是对权值排序,不是结点的ID(这个很容易搞错),然后就是对于两个序列的正反比较逻辑都得写,也就是对于同一个位置i,a[i]>b[i]和a[i]<b[i]的返回值都得明确写出来,并且,对于所有的完全一样的序列,也得做处理,否则测试点5出现段错误,总结一点就是排序函数得对所有的可能情况作出处理。
提交结果:
AC代码:
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
struct Node{
int weight;
vector<int> child;
}node[110];
vector<int> path;//当前搜索路径
vector<vector<int> > result;//所有满足条件的解
bool cmp(vector<int> a,vector<int> b){
int len = min(a.size(),b.size());
for(int i=0;i<len;++i){
if(node[a[i]].weight>node[b[i]].weight){
return true;
}else if(node[a[i]].weight<node[b[i]].weight){//这个不写会出现测试点2错误
return false;
}
}
return a.size()>b.size();// 不写这个出现段错误
}
void preTraverse(int root,int weight){
if(node[root].child.empty()){
// 叶子结点
path.push_back(root);
// 计算当前路径的权值
int sum = 0;
for(int i=0;i<path.size();++i){
sum += node[path[i]].weight;
}
if(sum==weight){
result.push_back(path);
}
//回退
path.pop_back();
return ;
}
//选择当前结点
path.push_back(root);
for(int i=0;i<node[root].child.size();++i){
preTraverse(node[root].child[i],weight);
}
path.pop_back();
}
int main(){
int N,M,S;//结点总数,非叶结点总数 ,待查询权值
scanf("%d %d %d",&N,&M,&S);
for(int i=0;i<N;++i){
scanf("%d",&node[i].weight);
}
int ID,K;
for(int i=0;i<M;++i){
scanf("%d %d",&ID,&K);
int child;
for(int j=0;j<K;++j){
scanf("%d",&child);
node[ID].child.push_back(child);
}
}
preTraverse(0,S);
// 按照字典序逆序输出result的序列
sort(result.begin(),result.end(),cmp);
for(int i=0;i<result.size();++i){
for(int j=0;j<result[i].size();++j){
printf("%d",node[result[i][j]].weight);
if(j<result[i].size()-1) printf(" ");
}
printf("\n");
}
return 0;
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。