Solution:
- 题目要求:给出一棵树,树的每个结点有对应的权重。给出一个目标权重,求从根结点到任意叶结点的路径上所有结点权重之和等于目标权重的所有路径。所有路径序列按照序列降序排列。根节点的编号为0。
- 输入:第一行三个正整数n,m,w;分别为总结点数,非叶子结点数以及目标权重。第二行为n个正整数,wi为第i个结点的权重。(0<=i<=n-1)。接下来m行,分别为每个非叶子结点的孩子结点信息。
- 输出:题目要求的所有路径。
- 我们要保证深度优先遍历时直接输出的是从大到小的顺序,就要在接收孩子结点数据时,每次读入完孩子结点的数据就要按照权值进行排序,根据权值改变结点的序号。
- 记录路径采取这样的方式:首先建立一个path数组,传入一个node_num记录对当前路径来说这是第几个结点(这样直接在path[node_num]里面存储当前结点的孩子结点的序号,这样可以保证在先判断return的时候,path是从0~node_num-1的值确实是要求的路径结点。然后每次要遍历下一个孩子结点的之前,令path[node_num] = 孩子结点的序号,这样就保证了在return的时候当前path里面从 0~nodenum-1的值就是要输出的路径的结点序号,输出这个序号的权值即可,直接在return语句里面输出。
- 注意:当 sum==目标权重 的时候,记得判断是否孩子结点是空,
要不然如果不空说明没有到底部,就直接return而不是输出路径。
代码如下:
//dfs搜索
#include<iostream>
#include<vector>
#include<algorithm>
#include<stdio.h>
using namespace std;
struct Node{
vector<int> child;
int weight;
}node[105];
int path[105];
int n,m,s;//n为结点数,m为非叶子结点数,s为目标总权重
int visit[105];//访问数组
bool cmp(int a,int b){
return node[a].weight>node[b].weight;
}
void dfs(int index,int node_num,int sum){//结点下标,node_num表示对一条路径而言
//该节点是第几个结点
if(sum>s){
return;
}
if(sum==s){
if(node[index].child.size()!=0){//若不是叶子结点
return;
}
for(int i=0;i<node_num;i++){//打印路径
printf("%d%c", node[path[i]].weight,i!=node_num-1?' ':'\n');
}
return;
}
for(int i=0;i<node[index].child.size();i++){
int c_child=node[index].child[i];
path[node_num]=c_child;
dfs(c_child,node_num+1,sum+node[c_child].weight);
}
}
int main(){
cin>>n>>m>>s;
for(int i=0;i<n;i++){
cin>>node[i].weight;
}
int id,c_num;//结点id和孩子结点数量
int cid;//孩子结点id
for(int i=0;i<m;i++){
cin>>id>>c_num;
for(int j=0;j<c_num;j++){
cin>>cid;
node[id].child.push_back(cid);
}
sort(node[id].child.begin(),node[id].child.end(),cmp);
}
dfs(0,1,node[0].weight);
return 0;
}