题目描述
小A所在的企业中,每个员工在请求授权的时候都需要向他上面的某一级领导提出申请。
为了避免混乱,一个员工只会向他的上级领导中技术能力与他最相近的那位领导提出申请。现在小A想知道每个人的申请对象是谁。
小A所在企业的组织架构可以用一棵有根树来描述。即除了树根对应的最高领导以外,每个人都有唯一的一个直屋领导。
同时,每个员工的技术能力均可以用一个正整数表示,称为技术等级。两个人之间的技术能力越近则他们的技术等级之差的绝对值越小。输入描述:
第一行有一个正整数 n(2≤n≤1000 00)。n 代表小 A所在企业中的员工数量。
第二行有 n-1个正整数,第i个数 fi(i<fi≤n)代表编号为i的员工的直属领导是fi,编号为n的员工是没有直属领导的最高级领导。
第三行有n个正整数,第i个数ai代表编号为i的员工的技术等级。技术等级的范围在1到n之间。
输出描述:
在一行中输出 n-1 个以空格分隔的正整教,行未不能有空格。第i个代表编号为i的员工请求授权时的申请对象。 如果某个员工有个技术能力与他最相近的上级领导,则他会选择在组织架构上离他最近的那一位。 示例:
输入:
6
3 3 5 5 6
2 5 4 1 3 6
输出:
5 3 5 5 6
思路
核心思想是利用深度优先搜索(DFS)在一棵树上为每个节点找到与其值最接近的节点,并输出这些节点的索引。它通过一个映射维护节点值到节点索引集合的关系,以便在遍历树的过程中快速查询与当前节点值最接近的节点。通过比较当前节点值与映射中已有的值,确定最接近的节点,并在遍历完成后输出每个节点的“最接近”节点索引。
代码
package main
import (
"fmt"
"math"
)
var (
// key: 能力等级 val: map[int]struct{} 用来存放所有能力等级为 val 的节点下标
// 这里使用 map 而不使用 []int 的原因是 dfs 回溯结束要删除这个节点下标,使用 map 更容易操作
mp map[int]map[int]struct{}
n int
// 能力数组
val []int
// 用来存放节点和其孩子的关系,比如 g[2] = [1 1 0 0 0 0] 说明节点 3 拥有两个孩子(节点 1 和节点 2)
g [][]int
ans []int
)
func main() {
fmt.Scanln(&n)
mp = make(map[int]map[int]struct{})
g = make([][]int, n)
val = make([]int, n)
ans = make([]int, n-1)
for i := 0; i < n-1; i++ {
var fi int
fmt.Scan(&fi)
fi--
g[fi] = append(g[fi], i)
}
for i := 0; i < n; i++ {
fmt.Scan(&val[i])
}
dfs(n - 1)
for i := 0; i < len(ans); i++ {
fmt.Printf("%d ", ans[i])
}
}
// 第一个节点的处理逻辑
/* func dfs(cur int) {
// 加入能力数组
m[val[cur]][cur] = struct{}{}
// dfs
for _, child := range g[cur] {
dfs(child)
}
// 回溯
delete(m[val[cur]], cur)
if len(m[val[cur]]) == 0 {
delete(m, val[cur])
}
} */
func dfs(cur int) {
// 自上而下
if cur != n-1 {
// 遍历能力数组
lead, diff := -1, math.MaxInt32
for level, nodeIndexSet := range mp {
/*
1. 正常情况
2. 特殊情况,假设当前节点的能力值为 3,同时存在了节点能力值为 2 和 4 的情况,那么按照题目要求取下标较小的
*/
if diff > abs(val[cur]-level) || (diff == abs(val[cur]-level) && getMinIndex(nodeIndexSet) < lead) {
diff = abs(val[cur] - level)
lead = getMinIndex(nodeIndexSet)
}
}
ans[cur] = lead + 1
}
// 加入能力数组(惰性初始化)
if _, exist := mp[val[cur]]; !exist {
mp[val[cur]] = make(map[int]struct{})
}
mp[val[cur]][cur] = struct{}{}
// dfs
for _, child := range g[cur] {
dfs(child)
}
// 回溯
delete(mp[val[cur]], cur)
if len(mp[val[cur]]) == 0 {
delete(mp, val[cur])
}
}
func abs(a int) int {
return int(math.Abs(float64(a)))
}
func getMinIndex(m map[int]struct{}) int {
minValue := n
for index := range m {
if index < minValue {
minValue = index
}
}
return minValue
}