题目描述
城市 A 新建了 n 个座房子,城市规划处用 n−1 条双向街道将房子连在一起,使得任意两座房子之间有且仅有一条道路可达。牛牛和牛妹将被随机分到两个房子,现在牛牛想知道,他和牛妹房子的最长路径是多少。
方法一:暴力解法
求解思路
对于求解本题,我们可以将房子看作节点,双向街道看作边,即n个节点,n-1条边,可以构成树。我们对每个叶节点做一次dfs,求出到其它叶节点的距离,然后我们保留最大值即可。
解题代码
class Solution {
#define pii pair<int, int>
private:
long long myans;
vector<pii> g[100000];
public:
void dfs(int x, int fa, long long sum = 0)
{ //dfs
for (auto cur: g[x])
{
int v = cur.first, w = cur.second;
if (v == fa) continue;
myans = max(sum + w, myans);
dfs(v, x, sum + w); // 继续dfs即可
}
}
long long solve(int n, vector<int>& u, vector<int>& v, vector<int>& w) {
for (int i = 0; i < n - 1; ++i)
{
g[u[i]].push_back({v[i], w[i]});
g[v[i]].push_back({u[i], w[i]});
}
for (int i = 1; i <= n; ++i)
{ //对每个叶节点做dfs
if (g[i].size() == 1)
dfs(i, i, 0);
}
return myans; // 返回结果即可
}
};复杂度分析
时间复杂度:使用到了dfs,与树的深度有关,因此时间复杂度为
空间复杂度:引入常数级数组g[100010],因此空间复杂度为
方法二:优化求解
求解思路
对于本题的求解,我们可以将该树转化为有根树,考虑树中任意两叶节点的最大距离,其中不需要经过根节点,然后通过dfs维护每个节点的最大子树的路径和,最后即可求出本题的答案。
解题代码
class Solution {
#define pii pair<int, int>
#define maxn 100000
private:
int n;
vector<pii> g[maxn];
long long f[maxn][2];
public:
void dfs(int x, int fa = 0)
{
for (auto cur: g[x])
{
int v = cur.first, w = cur.second;
if (v == fa) continue;
dfs(v, x);
if (f[x][0] < f[v][0] + w) // 比较树中任意两叶节点的距离
{
f[x][1] = f[x][0];
f[x][0] = f[v][0] + w;
}
else if (f[x][1] < f[v][0] + w)
{
f[x][1] = f[v][0] + w;
}
}
}
long long solve(int n, vector<int>& u, vector<int>& v, vector<int>& w) {
// write code here
for (int i = 0; i < n - 1; ++i)
{
g[u[i]].push_back({v[i], w[i]}); // 遍历每个叶节点
g[v[i]].push_back({u[i], w[i]});
}
dfs(1, 0);
long long myres = 0;
for (int i = 1; i <= n; ++i)
{
myres = max(myres, f[i][0] + f[i][1]); // 保存最大值
}
return myres; // 返回结果
}
};复杂度分析
时间复杂度:使用递归,因此时间复杂度为,其中N为树的深度
空间复杂度:引入常数级变量空间,因此空间复杂度为

京公网安备 11010502036488号