PAT 甲级 A1053 Path of Equal Weight (30 分)

题目在此:我是题目

先说一下近期反思吧。本来不准备再更新博客了的,原因是今年浙大太炸了,准备转换下目标,失去pat即失去动力更新csdn。但是翻来覆去心里还是喜欢浙大,那就考软院吧。不再浪费宝贵的前期时间来纠结目标院校了。希望自己能坚持下去…

说说题目把:

题意:

给定一个树和每个节点的权重,求所有从根结点到叶子节点的路径,使得每条路径上的结点的权值之和等于给定的常数S。如果有多条这样的路径,则按路径的非递增的顺序输出。(这个规则有点像字符串比较,如果前面的结点都相等,一旦接下来的这个不一样,就先输出那个大的那一条线。)

思路:

  1. 这是一颗普通性质的数,因此令结构体node存放结点的数据域和指针域,其中指针域使用vector存放所有的孩子结点的编号。又考虑到最后的输出需要按权值从大到小排序,因此不妨在读入时就事先对每个结点的子节点进行排序(即对vector中的结点按权值从大到小排序),这样在遍历时就会优先遍历到权值大的结点。
  2. 令int型数组path[maxn]存放递归过程中产生的路径上的结点编号。接下来进行DFS,参数有三个:当前访问的结点标号index、当前路径path上的结点个数numNode(也是递归层数)以及当前路径上的权值和sum。递归过程如下:
    1. 若sum>S 直接return
    2. 若sum==S 说明到当前访问结点index为止,输入中需要达到的S已经得到,这时如果结点index为子结点,则输出path数组中所有的数据;否则return。
    3. 若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;
}

看不懂头文件的童鞋戳这里:参考文章

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值