题目在此:我是题目
先说一下近期反思吧。本来不准备再更新博客了的,原因是今年浙大太炸了,准备转换下目标,失去pat即失去动力更新csdn。但是翻来覆去心里还是喜欢浙大,那就考软院吧。不再浪费宝贵的前期时间来纠结目标院校了。希望自己能坚持下去…
说说题目把:
题意:
给定一个树和每个节点的权重,求所有从根结点到叶子节点的路径,使得每条路径上的结点的权值之和等于给定的常数S。如果有多条这样的路径,则按路径的非递增的顺序输出。(这个规则有点像字符串比较,如果前面的结点都相等,一旦接下来的这个不一样,就先输出那个大的那一条线。)
思路:
- 这是一颗普通性质的数,因此令结构体node存放结点的数据域和指针域,其中指针域使用vector存放所有的孩子结点的编号。又考虑到最后的输出需要按权值从大到小排序,因此不妨在读入时就事先对每个结点的子节点进行排序(即对vector中的结点按权值从大到小排序),这样在遍历时就会优先遍历到权值大的结点。
- 令int型数组path[maxn]存放递归过程中产生的路径上的结点编号。接下来进行DFS,参数有三个:当前访问的结点标号index、当前路径path上的结点个数numNode(也是递归层数)以及当前路径上的权值和sum。递归过程如下:
- 若sum>S 直接return
- 若sum==S 说明到当前访问结点index为止,输入中需要达到的S已经得到,这时如果结点index为子结点,则输出path数组中所有的数据;否则return。
- 若sum<S 说明要求还未满足。此时枚举当前访问结点index的所有子节点,对每一个子结点child,先将其存入path[numNode],然后在此基础上往下一层递归,下一层的递归参数为child、numNode+1、sum+node[child].weight。
(不熟悉数的DFS算法的读者可以参考这个链接:参考文章)
最重要的注意点无非就是一定要按高权值路径依次输出。
AC代码:
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 110;
struct node{
int weight;
vector<int> child;
}Node[MAXN];
bool cmp(int a,int b){
return Node[a].weight>Node[b].weight;
}
int n,m,S;
int path[MAXN];
void DFS(int index,int numNode,int sum){
if(sum>S) return ;
if(sum==S){
if(Node[index].child.size() !=0) return;
for(int i = 0;i<numNode;i++){
printf("%d",Node[path[i]].weight);
if(i<numNode-1) printf(" ");
else printf("\n");
}
return ;
}
for(int i = 0;i<Node[index].child.size();i++){
int child = Node[index].child[i];
path[numNode] = child;
DFS(child,numNode+1,sum+Node[child].weight);
}
}
int main(){
scanf("%d%d%d",&n,&m,&S);
for(int i=0;i<n;i++){
scanf("%d",&Node[i].weight);
}
int id,k,child;
for(int i =0;i<m;i++){
scanf("%d%d",&id,&k);
for(int j = 0;j<k;j++){
scanf("%d",&child);
Node[id].child.push_back(child);
}
sort(Node[id].child.begin(),Node[id].child.end(),cmp);
}
path[0]=0;
DFS(0,1,Node[0].weight);
return 0;
}
看不懂头文件的童鞋戳这里:参考文章