原题:https://pintia.cn/problem-sets/994805342720868352/problems/994805424153280512
Sample Input:
20 9 24
10 2 4 3 5 10 2 18 9 7 2 2 1 3 12 1 8 6 2 2
00 4 01 02 03 04
02 1 05
04 2 06 07
03 3 11 12 13
06 1 09
07 2 08 10
16 1 15
13 3 14 16 17
17 2 18 19
Sample Output:
10 5 2 7
10 4 10
10 3 3 6 2
10 3 3 6 2
题目大意
给出树的结构和树上结点的权重,找到从根结点到叶子节点上权重相加等于给定目标数的路径,并按照权重从到到小输入路径。
题目分析
找到权重为某一值的路径,从根结点进行深度优先遍历(DFS)到叶子结点的时候判断权重总值是否符合要求即可。但是按照非降序输入,类似于字符串比较间的字典序,需要依次比较路径结点的权值,所以,为了方便,我们可以在输入完一个结点的孩子结点后,就对其孩子结点按照权重从大到小排序,让权重大的在前面,最后进行DFS后的结果就是符合条件的。
/* 1053 Path of Equal Weight (30 分) */
// 使用链表或者多维向量存储图
// 使用深度优先遍历找路径的长度
// 可以先将子节点按照权重进行排序,这样DFS后就是非升序
#include<vector>
#include<algorithm>
#include<iostream>
using namespace std;
const int MAXNUM = 100; // 最大结点数目
int weight[MAXNUM];
vector<vector<int> > map(MAXNUM); // 邻接表
vector<int> path; // 结果路径
int n, m, s;
int cmp(int a, int b) {
return weight[a] > weight[b];
}
void dfs(int node,int dis) {
dis += weight[node];
if (dis > s) return; // 权重超出范围
path.push_back(node);
if (map[node].size() == 0) { // 叶子结点
if (dis == s) {
for (int i = 0; i < path.size(); i++) {
printf("%d%c", weight[path[i]], i == path.size() - 1 ? '\n' : ' ');
}
}
}
else { // dfs孩子结点
for (int i = 0; i < map[node].size(); i++) dfs(map[node][i], dis);
}
path.pop_back();
}
int main() {
scanf("%d %d %d", &n, &m, &s);
map.resize(n);
for (int i = 0; i < n; i++) scanf("%d", &weight[i]);
int node, cnt, child;
for (int i = 0; i < m; i++) {
scanf("%d %d", &node, &cnt);
for (int j = 0; j < cnt; j++) {
scanf("%d", &child);
map[node].push_back(child);
}
// 先进行排序,大权重在前
sort(map[node].begin(), map[node].end(), cmp);
}
// 深度优先搜索找路径
dfs(0,0);
return 0;
}