题目大意
给出一棵树,找从根结点到叶子结点的路径上的权值相加之和等于给定目标数的路径,并且按照“首位最大”原则输出路径。
思路解析
树是一种特殊的图,所以本题本质上考察的是图的遍历,当然也可以当做树来处理。我一向主张以不变应万变,所以个人推荐使用图的算法,这样才能有迹可循。套路依然是dfs,只不过在输出的时候稍微复杂一些,请留意我设计的cmp比较函数。
示例代码
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int weight[100], gra[100][100];
vector<int> vec;
vector<vector<int>> path;
int n, m, s,sum = 0;
void dfs(int v) {
vec.push_back(v);
sum += weight[v];
if (sum == s) {
for (int i = 0; i < n; i++) {
if (gra[v][i] == 1) {
vec.pop_back();
sum -= weight[v];
return;
}
}
path.push_back(vec);
vec.pop_back();
sum -= weight[v];
return;
}
else if (sum > s) {
vec.pop_back();
sum -= weight[v];
return;
}
for (int i = 1; i < n; i++) {
if (gra[v][i] == 1)
dfs(i);
}
vec.pop_back();
sum -= weight[v];
}
bool cmp(vector<int> v1,vector<int> v2) {
for (int i = 0; i < v1.size() && i < v2.size(); i++) {
if (v1[i] > v2[i])
return true;
else if (v1[i] == v2[i])
continue;
else
return false;
}
return false;
}
int main() {
scanf("%d %d %d", &n, &m, &s);
for (int i = 0; i < n; i++)
scanf("%d", &weight[i]);
for (int i = 0; i < m; i++) {
int a,b,k;
scanf("%d %d", &a, &k);
for (int j = 0; j < k; j++) {
scanf("%d", &b);
gra[a][b] = 1;
}
}
dfs(0);
for (int i = 0; i < path.size(); i++) {
for (int j = 0; j < path[i].size(); j++)
path[i][j] = weight[path[i][j]];
}
sort(path.begin(), path.end(), cmp);
for (int i = 0; i < path.size(); i++) {
printf("%d", path[i][0]);
for (int j = 1; j < path[i].size(); j++) {
printf(" %d", path[i][j]);
}
printf("\n");
}
return 0;
}