3203. 合并两棵树后的最小直径
题目描述:
题如其意,给你两棵树,你可以从两棵树中各挑一个点出来,连一条边,形成一个新的树,问你最小直径是多少
- 1 < = n , m < = 1 0 5 1 <= n, m <= 10^5 1<=n,m<=105
思路:
打力扣还是先观察一下数据范围的提示,发现给的两棵树的下标都是从0开始,所以正解可能不希望你把两棵树真正合并成一棵树做
选的点肯定在直径上,且是直径的中点
设a,b分别是两棵树的直径长度,则答案有三种情况:
- 第一棵树的直径很长,连边后新树的直径仍未第一棵树的直径,答案是a
- 第二棵树的直径很长,连边后新树的直径仍未第二棵树的直径,答案是b
- 新树的直径经过刚添加的边,则答案是 ⌈ a 2 ⌉ + ⌈ b 2 ⌉ + 1 \lceil{\frac{a}{2}} \rceil+\lceil{\frac{b}{2}}\rceil + 1 ⌈2a⌉+⌈2b⌉+1
class Solution {
public:int fuck(vector<vector<int>>& g){vector<vector<int>>G(g.size() + 1);for(auto x : g){G[x[0]].push_back(x[1]);G[x[1]].push_back(x[0]);}int ans = 0;auto dfs = [&](auto && dfs, int x, int fa) -> int{int maxn = 0;for(auto y : G[x]){if(y == fa)continue;int res = dfs(dfs, y, x) + 1;ans = max(ans, res + maxn);maxn = max(maxn, res);}return maxn;};dfs(dfs, 0, -1);return ans;}int minimumDiameterAfterMerge(vector<vector<int>>& G1, vector<vector<int>>& G2) {int a = fuck(G1), b = fuck(G2);int ans = max(max(a, b), (a+1) / 2 + (b + 1) / 2 + 1);return ans;}
};