【ACWing】1073. The center of the tree

Subject address:

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

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. Please find a point in the tree so that the farthest distance from this point to other nodes in the tree is the closest.

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, representing the farthest distance from the requested point to other nodes in 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 ≤ c i ≤ 1 0 5 1≤c_i≤10^5 1ci105

The idea is DFS, to enumerate each vertex, it may be set to enumerate xxx , find the length of the longest path starting from the vertex, and then find the node with the shortest longest path. We take any vertex as the root of the tree, and then treat the entire tree as a rooted tree, so that all paths can be classified according to the highest point it passes, and then the vertices are enumeratedxxx , find out asxxx is the longest path length of the highest point. Letf (x) f(x)f ( x ) is fromxxThe longest path among all paths that x goes down, letg (x) g(x)g ( x ) is fromxxx is the longest path of all the paths going up. LetxxThe children of x havec 1, c 2,..., ck c_1,c_2,...,c_kc1,c2,...,ck, 那么f (x) = ∣ (x, ci) ∣ + f (ci) f (x) = | (x, c_i) | + f (c_i)f(x)=(x,ci)+f(ci) , this can be solved directly by DFS. But forg(x) g(x)g ( x ) is a little more complicated, letpx p_xpxIs xxthe father of x , theng (x) g(x)g ( x ) must go up one step first, but how to go next has to be classified. First, it is possible to continue to go upward, then it is∣ (x, px) ∣ + g (px) |(x,p_x)|+g(p_x)(x,px)+g(px) ; It is also possible to go down, but you can't go back toxx ifyou go downx , we can think about it this way, iff (px) f(p_x)f(px) Is not passedxxx , then the way down can be taken tof (px) f(p_x)f(px) ; otherwise, find and remove the passxxAfter the path of x , the longest path in the remaining paths. So we are countingffWhen f , also record fromxxThe longest and the second longest path in the downward path of x have passed through which son (note that the longest and second longest paths here are classified according to which son passed, that is,f (ci) f(c_i)f(ci) Take the largest and second largestci c_ici). code show as below:

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

// 边数是顶点数乘以2
const int N = 10010, M = 2 * N;
int n;
int h[N], e[M], ne[M], w[M], idx;
// d1[x]是从x向下走的第一长的路径长度,d2[x]是从x向下走的第二长的路径长度;
// p1[x]是从x向下走的第一长的路径长度经过的孩子节点编号,p2[x]是从x向下走的
// 第二长的路径长度经过的孩子节点编号;up[x]是从x向上走的最长路径长度;
// 以上所说路径都是不自交的路径
int d1[N], d2[N], p1[N], p2[N], up[N];

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

// 求从u出发向下走的最长和次长路径长度,及它们经过的孩子编号
int dfs_d(int u, int parent) {
    
    
	// 枚举u的孩子
    for (int i = h[u]; i != -1; i = ne[i]) {
    
    
        int j = e[i];
        // 不走回头路
        if (j == parent) continue;
		
		// 递归求解从j出发向下的最长路径长度
        int d = dfs_d(j, u) + w[i];
        if (d >= d1[u]) {
    
    
            d2[u] = d1[u], d1[u] = d;
            p2[u] = p1[u], p1[u] = j;
        } else if (d > d2[u]) {
    
    
            d2[u] = d;
            p2[u] = j;
        }
    }

    return d1[u];
}

// 求从u出发向上走的最长路径长度
void dfs_u(int u, int parent) {
    
    
    for (int i = h[u]; i != -1; i = ne[i]) {
    
    
        int j = e[i];
        if (j == parent) continue;
		
		// 如果从u出发向下走的最长路就是通过j的,那么就应该累加从u向上走的
		// 最长路长度和从u向下走的第二长路长度之更大者;否则累加从u向上走的
		// 最长路长度和从u向下走的最长路长度之更大者;
        if (p1[u] == j) up[j] = max(up[u], d2[u]) + w[i];
        else up[j] = max(up[u], d1[u]) + w[i];

        dfs_u(j, u);
    }
}

int main() {
    
    
    cin >> n;

    memset(h, -1, sizeof h);
    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_d(1, -1);
    dfs_u(1, -1);

    int res = 0x3f3f3f3f;
    for (int i = 1; i <= n; i++) res = min(res, max(d1[i], up[i]));

    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/114713481