最长距离

最长路径

https://www.nowcoder.com/questionTerminal/430ded6b482d4d8bbcf2eca6f20e62e3

思路

朴素做法

对每个节点做一次dfs,求出其到其他节点的距离,期间保留最大值即可。

时间复杂度

该做法可通过 的数据

Code

class Solution {
#define pii pair<int, int>
#define ll long
private:
    ll ans;
    vector<pii> g[100010];
public:
    void dfs(int x, int fa, int sum = 0) {
        for (auto cur: g[x]) {
            int v = cur.first, w = cur.second;
            if (v == fa) continue;
            ans = max(sum + w, ans);
            dfs(v, x, sum + w);
        }
    }
    ll 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]});
        }
        for (int i = 1; i <= n; ++i) {
            dfs(i, i, 0);
        }
        return ans;
    }
};

初步优化

对每个叶节点做一次dfs,求出其到其他叶节点的距离,期间保留最大值即可。

最差时间复杂度

该做法可通过 的数据

Code

class Solution {
#define pii pair<int, int>
#define ll long long
private:
    ll ans;
    vector<pii> g[100010];
public:
    void dfs(int x, int fa, ll sum = 0) {
        for (auto cur: g[x]) {
            int v = cur.first, w = cur.second;
            if (v == fa) continue;
            ans = max(sum + w, ans);
            dfs(v, x, sum + w);
        }
    }
    ll 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]});
        }
        for (int i = 1; i <= n; ++i) {
            if (g[i].size() == 1)
                dfs(i, i, 0);
        }
        return ans;
    }
};

标程做法

首先可将该树转化为有根树,考虑为树中的任意两叶节点点的最大距离,不一定经过根节点。
由于是多叉树,最大路径一定是路径和最大的两棵子树的路径和之和。
在dfs过程中可以维护每个结点的两棵最大子树的路径和,保留最大值即可。

时间复杂度

Code

class Solution {
#define pii pair<int, int>
#define maxn 100010
#define ll long long
private:
    int n;
    vector<pii> g[maxn];
    ll f[maxn][2];  //可在dfs过程中用两个变量优化, f[i][0] 表示最大值,f[i][1] 表示次大值
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;
            }
        }
    }
    ll 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);
        ll res = 0;
        for (int i = 1; i <= n; ++i) {
            res = max(res, f[i][0] + f[i][1]);
        }
        return res;
    }
};
全部评论
感觉第二种也是O(n),无向图,随便哪个点开始dfs,每次都比较,最后也能求到全局最大
点赞 回复 分享
发布于 2021-05-17 16:03

相关推荐

双非Java现在无实习,应该好好背八股,找个开源项目做做,还是应该疯狂投实习呢?
Aries_woon:投实习并不耽误你做开源项目,集中一个下午可以投几十家实习了,投完安心做项目等待面试通知
点赞 评论 收藏
分享
12-01 12:34
已编辑
广东工业大学 Java
如题,fw🐭🐭,加上准备的太晚,大三上已找不到日常实习,导致连锁反应,下学期的暑期实习找不到好的实习,导致秋招找不到中大厂,现在是中小厂Java还有考公的选择,由于有些中小厂工作强度比肩大厂,钱还少,感觉不如考公如果🐮u们是我现在这种情况,会怎么选?
负债的混子:关注你一段时间了,突然发现你头像名字都改了,想必是这段时间压力很大。关于就业还是考公的选择,就像很多牛友说的:不要美化自己没走过的路。你现在想往互联网发展,发现这条路很难走,然后想往考公发展,但是你没走过考公这条路,所以你不知道这条路的压力如何。你今年大三了,还有时间给你做选择,我希望你能够尽快的决定自己的方向,然后一条路走到黑,而不是在这里徘徊,每个人的道路是不一样的,你无法复刻别人的路,你能做的就是尽力的完善自己。 最后,我想说的是,加油,陌生人!
点赞 评论 收藏
分享
贪食滴🐶:你说熟悉扣篮的底层原理,有过隔扣职业球员的实战经验吗
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务