【LetMeFly】3372.连接两棵树后最大目标节点数目 I:脑筋急转弯——深搜确定k邻近节点(清晰题解)
力扣题目链接:https://leetcode.cn/problems/maximize-the-number-of-target-nodes-after-connecting-trees-i/
有两棵 无向 树,分别有 n
和 m
个树节点。两棵树中的节点编号分别为[0, n - 1]
和 [0, m - 1]
中的整数。
给你两个二维整数 edges1
和 edges2
,长度分别为 n - 1
和 m - 1
,其中 edges1[i] = [ai, bi]
表示第一棵树中节点 ai
和 bi
之间有一条边,edges2[i] = [ui, vi]
表示第二棵树中节点 ui
和 vi
之间有一条边。同时给你一个整数 k
。
如果节点 u
和节点 v
之间路径的边数小于等于 k
,那么我们称节点 u
是节点 v
的 目标节点 。注意 ,一个节点一定是它自己的 目标节点 。
请你返回一个长度为 n
的整数数组 answer
,answer[i]
表示将第一棵树中的一个节点与第二棵树中的一个节点连接一条边后,第一棵树中节点 i
的 目标节点 数目的 最大值 。
注意 ,每个查询相互独立。意味着进行下一次查询之前,你需要先把刚添加的边给删掉。
示例 1:
输入:edges1 = [[0,1],[0,2],[2,3],[2,4]], edges2 = [[0,1],[0,2],[0,3],[2,7],[1,4],[4,5],[4,6]], k = 2
输出:[9,7,9,8,8]
解释:
- 对于
i = 0
,连接第一棵树中的节点 0 和第二棵树中的节点 0 。 - 对于
i = 1
,连接第一棵树中的节点 1 和第二棵树中的节点 0 。 - 对于
i = 2
,连接第一棵树中的节点 2 和第二棵树中的节点 4 。 - 对于
i = 3
,连接第一棵树中的节点 3 和第二棵树中的节点 4 。 - 对于
i = 4
,连接第一棵树中的节点 4 和第二棵树中的节点 4 。
示例 2:
输入:edges1 = [[0,1],[0,2],[0,3],[0,4]], edges2 = [[0,1],[1,2],[2,3]], k = 1
输出:[6,3,3,3,3]
解释:
对于每个 i
,连接第一棵树中的节点 i
和第二棵树中的任意一个节点。

提示:
2 <= n, m <= 1000
edges1.length == n - 1
edges2.length == m - 1
edges1[i].length == edges2[i].length == 2
edges1[i] = [ai, bi]
0 <= ai, bi < n
edges2[i] = [ui, vi]
0 <= ui, vi < m
- 输入保证
edges1
和edges2
都表示合法的树。 0 <= k <= 1000
解题方法:深度优先搜索
解题思路
tree1和tree2之间连一条线,使得距离tree1节点i不超过k的节点数尽可能多,如何做?
首先确定tree1中选择哪个节点:
这还用问?当然选节点 i i i了。
连另一个节点j多话,tree2任一节点到tree1节点i的距离一定比到节点j的远。
然后确定tree2中连哪个节点:
有没有一种可能tree2中每次连接的节点都是可以确定的?
当然, t r e e 1 中节点 i 到 t r e e 2 中节点 j 的距离 = t r e e 2 中被连接点到 t r e e 2 中节点 j 的距离 + 1 tree1中节点i到tree2中节点j的距离=tree2中被连接点到tree2中节点j的距离+1 tree1中节点i到tree2中节点j的距离=tree2中被连接点到tree2中节点j的距离+1
想让tree2到tree1.i距离不超过k的节点尽可能多,不就是tree2到tree2.j距离不超过k-1的节点尽可能多吗?
tree2自身是不会变的,所以每次都选tree2中 k − 1 k-1 k−1邻近节点最多的那个点就好了。
具体方法
写一个函数把边变成树(tree[i]存储节点i的所有相邻节点);
写一个dfs
函数接收一棵树
、当前遍历到的节点
、上一个节点
、可用距离还有多少
这几个参数,返回当前节点的k范围内有多少节点。
首先创建第二棵树,求出这棵树每个节点中 k − 1 k-1 k−1邻近节点最多的那个(记为toAdd);
接着创建第一棵树,求出每棵树的 k k k邻近节点个数并加上 t o A d d toAdd toAdd即可。
时空复杂度分析
- 时间复杂度 O ( m 2 + n 2 ) O(m^2+n^2) O(m2+n2)
- 空间复杂度 O ( 1 ) O(1) O(1),力扣算法返回值不计入空间复杂度
AC代码
C++
/** @Author: LetMeFly* @Date: 2025-05-28 21:43:27* @LastEditors: LetMeFly.xyz* @LastEditTime: 2025-05-28 22:55:41*/
class Solution {
private:vector<vector<int>> buildTree(vector<vector<int>>& edges) {vector<vector<int>> graph(edges.size() + 1);for (vector<int>& edge : edges) {graph[edge[0]].push_back(edge[1]);graph[edge[1]].push_back(edge[0]);}return graph;}int dfs(vector<vector<int>>& graph, int lastNode, int thisNode, int k) {if (k < 0) {return 0;}int ans = 1;for (int nextNode : graph[thisNode]) {if (nextNode == lastNode) {continue;}ans += dfs(graph, thisNode, nextNode, k - 1);}return ans;}
public:vector<int> maxTargetNodes(vector<vector<int>>& edges1, vector<vector<int>>& edges2, int k) {vector<vector<int>> graph2 = buildTree(edges2);int add = 0;for (int i = 0; i <= edges2.size(); i++) {add = max(add, dfs(graph2, -1, i, k - 1));}vector<vector<int>> graph1 = buildTree(edges1);vector<int> ans(graph1.size());for (int i = 0; i < ans.size(); i++) {ans[i] = dfs(graph1, -1, i, k) + add;}return ans;}
};
Python
'''
Author: LetMeFly
Date: 2025-05-28 21:43:27
LastEditors: LetMeFly.xyz
LastEditTime: 2025-05-28 23:05:02
'''
from typing import Listclass Solution:def buildTree(self, edges: List[List[int]]) -> List[List[int]]:ans = [[] for _ in range(len(edges) + 1)]for x, y in edges:ans[x].append(y)ans[y].append(x)return ansdef dfs(self, tree: List[List[int]], lastNode: int, thisNode: int, k: int) -> int:if k < 0:return 0ans = 1for nextNode in tree[thisNode]:if nextNode != lastNode:ans += self.dfs(tree, thisNode, nextNode, k - 1)return ansdef maxTargetNodes(self, edges1: List[List[int]], edges2: List[List[int]], k: int) -> List[int]:tree2 = self.buildTree(edges2)toAdd = max(self.dfs(tree2, -1, i, k - 1) for i in range(len(tree2)))tree1 = self.buildTree(edges1)return [self.dfs(tree1, -1, i, k) + toAdd for i in range(len(tree1))]
Java
/** @Author: LetMeFly* @Date: 2025-05-28 21:43:27* @LastEditors: LetMeFly.xyz* @LastEditTime: 2025-05-28 23:21:21*/
import java.util.List;
import java.util.ArrayList;class Solution {private List<Integer>[] buildTree(int[][] edges) {List<Integer>[] ans = new ArrayList[edges.length + 1];for (int i = 0; i < ans.length; i++) {ans[i] = new ArrayList<>();}for (int[] edge : edges) {ans[edge[0]].add(edge[1]);ans[edge[1]].add(edge[0]);}return ans;}private int dfs(List<Integer>[] tree, int lastNode, int thisNode, int k) {if (k < 0) {return 0;}int ans = 1;for (int nextNode : tree[thisNode]) {if (nextNode != lastNode) {ans += dfs(tree, thisNode, nextNode, k - 1);}}return ans;}public int[] maxTargetNodes(int[][] edges1, int[][] edges2, int k) {List<Integer>[] tree2 = buildTree(edges2);int add = 0;for (int i = 0; i < tree2.length; i++) {add = Math.max(add, dfs(tree2, -1, i, k - 1));}List<Integer>[] tree1 = buildTree(edges1);int[] ans = new int[tree1.length];for (int i = 0; i < ans.length; i++) {ans[i] = add + dfs(tree1, -1, i, k);}return ans;}
}
Go
/** @Author: LetMeFly* @Date: 2025-05-28 21:43:27* @LastEditors: LetMeFly.xyz* @LastEditTime: 2025-05-29 00:43:41*/
package mainfunc buildTree3372(edges [][]int) [][]int {ans := make([][]int, len(edges) + 1)for _, edge := range edges {ans[edge[0]] = append(ans[edge[0]], edge[1])ans[edge[1]] = append(ans[edge[1]], edge[0])}return ans
}func dfs3372(tree [][]int, lastNode, thisNode, k int) int {if k < 0 {return 0}ans := 1for _, nextNode := range tree[thisNode] {if nextNode != lastNode {ans += dfs3372(tree, thisNode, nextNode, k - 1)}}return ans
}func maxTargetNodes(edges1 [][]int, edges2 [][]int, k int) []int {tree2 := buildTree3372(edges2)toAdd := 0for i := range tree2 {toAdd = max(toAdd, dfs3372(tree2, -1, i, k - 1))}tree1 := buildTree3372(edges1)ans := make([]int, len(tree1))for i := range ans {ans[i] = toAdd + dfs3372(tree1, -1, i, k)}return ans
}
同步发文于CSDN和我的个人博客,原创不易,转载经作者同意后请附上原文链接哦~
千篇源码题解已开源