P4408 [NOI2003] The diameter of the tree

Title

Portal P4408 [NOI2003] Children who play truant

answer

Set path (C, A) (C, A)(C,A ) and path(A, B) (A, B)(A,The first intersection of B ) isDDD , the problem is equivalent to starting fromAAA starts and finds two paths(A, B), (A, C) (A,B),(A,C)(A,B),(A,C) 且满足 d i s t ( A , D ) ≤ d i s t ( D , B ) dist(A,D)\leq dist(D,B) dist(A,D)dist(D,B),使 d i s t ( A , B ) + d i s t ( A , C ) dist(A,B)+dist(A,C) dist(A,B)+dist(A,C ) Maximum. LetA, BA, BA,B is the end point of a certain path, then the answer is dist (A, B) + dist (C, D) + min ⁡ [dist (A, D), dist (D, B)], D ∈ path (A, B ) dist(A,B)+dist(C,D)+\min[dist(A,D),dist(D,B)],D\in path(A,B)dist(A,B)+d i s t ( C ,D)+min[dist(A,D),dist(D,B)],Dpath(A,B ) Let(A, D) (A, D)(A,D ) or(D, B) (D, B)(D,B ) is part of the bifurcation of the diameter of the tree. According to the longest diameter, replacing it with the diameter of the tree will not make the answer worse. ThenDFS DFSD F S solves the diameter of a certain tree, againDFS DFSD F S solves the longest distance from each point on the diameter to its subtree node, and updates the answer by enumerating the points on the path. Total time complexityO (N) O (N)O ( N )

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 200005;
int N, M, pre[maxn], num, rec[maxn];
int tot, head[maxn], to[maxn << 1], cost[maxn << 1], nxt[maxn << 1];
ll mx[maxn], ds[maxn];
bool in[maxn];

inline void add(int x, int y, int z)
{
    
    
    to[++tot] = y, cost[tot] = z, nxt[tot] = head[x], head[x] = tot;
}

void dfs(int x, int f, ll w, int &t)
{
    
    
    ds[x] = w, pre[x] = f;
    if (ds[x] >= ds[t])
        t = x;
    for (int i = head[x]; i; i = nxt[i])
    {
    
    
        int y = to[i], z = cost[i];
        if (y != f)
            dfs(y, x, w + z, t);
    }
}

void dfs2(int x, int f, ll w)
{
    
    
    mx[x] = w;
    for (int i = head[x]; i; i = nxt[i])
    {
    
    
        int y = to[i], z = cost[i];
        if (!in[y] && y != f)
            dfs2(y, x, w + z), mx[x] = max(mx[x], mx[y]);
    }
}

int main()
{
    
    
    scanf("%d%d", &N, &M);
    for (int i = 1, x, y, z; i <= M; ++i)
        scanf("%d%d%d", &x, &y, &z), add(x, y, z), add(y, x, z);
    int s = 1, t = 0;
    dfs(s, 0, 0, t);
    s = t, t = 0;
    dfs(s, 0, 0, t);
    for (int i = t; i; i = pre[i])
        rec[++num] = i, in[i] = 1;
    for (int i = 1; i <= num; ++i)
        dfs2(rec[i], 0, 0);
    ll dm = ds[t], res = 0;
    for (int i = 1, p; i <= num; ++i)
        p = rec[i], res = max(res, dm + mx[p] + min(ds[p], dm - ds[p]));
    printf("%lld\n", res);
    return 0;
}

Guess you like

Origin blog.csdn.net/neweryyy/article/details/114685379