1

题目大意:

给定一颗树和每个结点的权值,求从所有根结点到叶子结点的路径,使得每条路径上的权值之和等于给定的常数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出现段错误,总结一点就是排序函数得对所有的可能情况作出处理。

提交结果:

图片.png

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;
}

乔梓鑫
569 声望17 粉丝

主要分享个人学习经验和心得