P4408 [NOI2003]木の直径

題名

ポータルP4408 [NOI2003]不登校をする子供たち

回答

パスの設定(C、A)(C、A)C A とパス(A、B)(A、B)A B の最初の交点はDDですD、問題はAAから開始するのと同じですAが開始し、2つのパス(A、B)、(A、C)(A、B)、(A、C)を見つけますA B A C And满足dist(A、D)≤dist(D、B)dist(A、D)\ leq dist(D、B)d i s t A D d i s t D B 、使者dist(A、B)+ dist(A、C)dist(A、B)+ dist(A、C)d i s t A B +d i s t A C 最大。A、BA、BにしましょうA Bは特定のパスの終点であり、答えは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)d i s t A B +d i s t C D +min [ d i s t A D d i s t D B ] Dp a t h A B レッツ(A、D)(A、D)A D または(D、B)(D、B)D B は木の直径の分岐点の一部です。最長の直径によると、それを木の直径に置き換えても答えは悪くなりません。次にDFSDFSD F Sは、特定のツリーの直径を解決します。これもDFS DFSD F Sは、直径上の各ポイントからそのサブツリーノードまでの最長距離を解決し、パス上のポイントを列挙することによって回答を更新します。合計時間計算量O(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;
}

おすすめ

転載: blog.csdn.net/neweryyy/article/details/114685379