[ACWing] 1072. The longest path of the tree

Subject address:

https://www.acwing.com/problem/content/1074/

Given a tree, the tree contains nnn nodes (number1 ∼ n 1\sim n1n ) andn − 1 n−1n 1 undirected edge, and each edge has a weight. Now please find the longest path in the tree. In other words, find a path such that the distance between the points at both ends of the path is the farthest. Note: Only one point can be included in the path.

Input format: the
first line contains the integer nnn . Nextn − 1 n−1n 1 line, each line contains three integersai, bi, ci a_i,b_i,c_iai,bi,ci, Which means point ai a_iaiJapanese bi b_ibiThere is a weight between ci c_ici的边。 The side.

Output format:
output an integer that represents the length of the longest path of the tree.

Data range:
1 ≤ n ≤ 10000 1≤n≤100001n10000
1 ≤ a i , b i ≤ n 1≤a_i,b_i≤n 1ai,bin
− 1 0 5 ≤ c i ≤ 1 0 5 −10^5≤c_i≤10^5 105ci105

First use the adjacency table to build a map, you can use any point as the root of the tree, and then perform DFS. We enumerate the length of the longest path through the point when each point is the highest point. Set the point number as xxx , and the maximum path sum of all paths starting from it and going down (we regard the whole graph as a rooted tree) isf (x) f(x)f ( x ) , letxxThe children of x arec 1,..., ck c_1,...,c_kc1,...,ck,则有: f ( x ) = max ⁡ { f ( c i ) + ∣ ( x , c i ) ∣ } f(x)=\max\{f(c_i)+|(x,c_i)|\} f(x)=max{ f(ci)+(x,ci) } Letf (ci) + ∣ (x, ci) ∣ f(c_i)+|(x,c_i)|f(ci)+(x,ci) | Largest and the second largest of the twoci c_iciRespectively c 1 c_1c1And c 2 c_2c2The longest path can be defined by max ⁡ {0, f (c 1) + ∣ (x, c 1) ∣} + max ⁡ {0, f (c 2) + ∣ (x, c 2) ∣) \max\ {0,f(c_1)+|(x,c_1)|\}+\max\{0,f(c_2)+|(x,c_2)|\}max{ 0,f(c1)+(x,c1)}+max{ 0,f(c2)+(x,c2)},以上 ∣ ( x , c i ) ∣ |(x,c_i)| (x,ci) means to connectxxx c i c_i ciThe length of the side. Here and 0 00 takesmax ⁡ \maxmax means, if fromxxIf x takes the downward path of a child and is a negative number, it is better not to add this path. If it is not added, it will be0 00

There is one detail to pay attention to. Since the above algorithm takes a certain point as the root of the tree, and then regards the whole tree as a rooted tree, when enumerating each point, only calculate the downward direction from it. Path, and can’t go up anymore. There are two main ways to do this, either open a bool array to record whether a vertex has been visited, and if it has been visited before, it will not be visited again; or the father can be passed in as a parameter to traverse the neighboring points of the current node At the time, skip its parent node.

code show as below:

#include <iostream>
#include <cstring>
using namespace std;

const int N = 10010, M = 2 * N;
int n, res;
int h[N], e[M], ne[M], w[M], idx;

void add(int a, int b, int c) {
    
    
    e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
}

// 返回从u出发向下能走的权值和最大的路径的权值和
int dfs(int u, int parent) {
    
    
    int dist = 0;
    // 分别存最大和次大
    int d1 = 0, d2 = 0;

    for (int i = h[u]; i != -1; i = ne[i]) {
    
    
        int j = e[i];
        // 略过父亲节点
        if (j == parent) continue;

        int d = dfs(j, u) + w[i];
        dist = max(dist, d);

        if (d >= d1) d2 = d1, d1 = d;
        else if (d > d2) d2 = d;
    }

    res = max(res, d1 + d2);

    return dist;
}

int main() {
    
    
    memset(h, -1, sizeof h);

    cin >> n;
    for (int i = 0; i < n - 1; i++) {
    
    
        int a, b, c;
        cin >> a >> b >> c;
        add(a, b, c), add(b, a, c); 
    }

    dfs(1, -1);
    cout << res << endl;

    return 0;
}

Time and space complexity O (n) O(n)O ( n )

Guess you like

Origin blog.csdn.net/qq_46105170/article/details/114684812