题目大意:给出一颗0为树根的树,每个结点均有一个权值,询问以结点为根的子结点中最大的三个值,若不够三个结点则返回-1.
解题思路:因为是一颗树的形态,而要求子结点中的最大的三个值。因此最直观的想法就是从树的底部开始想根节点进行更新。这样进行更新遍历一次后,对各个结点的询问就可以直接给出。相应的做法是用vector来存储各个结点的父子关系,用dfs从底部开始向上进行遍历更新整个树,详见code。
题目来源:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4381
code:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
const int MAXN = 1e4+10;
int n,a,b,q,x;
int ans[MAXN][7];
vector<int> v[MAXN];
bool cmp(int a,int b){return a>b;}
void dfs(int x){
while(!v[x].empty()){
int p=v[x].back(); //获取x结点最后一个子结点
v[x].pop_back(); //弹出该结点
dfs(p); //继续迭代,直到树的叶子
for(int i=3;i<6;++i) //接收儿子结点的值
ans[x][i]=ans[p][i-3];
sort(ans[x],ans[x]+6,cmp); //排序存储最大的
}
}
int main(){
//freopen("input.txt","r",stdin);
while(~scanf("%d",&n)){
memset(ans,-1,sizeof(ans)); //初始为无子结点
scanf("%d",&ans[0][0]); //接收根结点
for(int i=1;i<n;++i){
scanf("%d%d",&a,&b);
v[a].push_back(i); //存储父亲结点的子结点,邻接表
ans[i][0]=b; //更新对应结点的权值
}
dfs(0); //进行由底向上地更新各个结点
scanf("%d",&q);
while(q--){
scanf("%d",&x);
if(ans[x][2]==-1) //如果子结点数量小于2,则返回-1
printf("-1\n");
else
printf("%d %d %d\n",ans[x][0],ans[x][1],ans[x][2]);
}
}
return 0;
}