洛谷题单指南-图论之树-P4408 [NOI2003] 逃学的小孩

原题链接:https://www.luogu.com.cn/problem/P4408

题意解读:树形结构中三个点C、A、B,C->A的路径小于C->B的路径,求C->A->B的可能的最长路径。

解题思路:

1、C->A以及C->B的距离有限制,但是A->B是没有限制的,显然越大越好,那么A->B应该取直径

2、接下来,C应该是距离直径两个端点距离较小的最大值

3、从直径两个端点分别跑一遍dfs,可以求出每个点到直径端点的距离

4、最终答案,枚举每一个点,取与两个直径端点距离较小的最大值,再加上直径长度

100分代码:

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;
const int N = 200005;

struct Node
{
    int v, w;
};
vector<Node> g[N];
int st, ed; //直径端点
LL maxdist; //直径长度
LL d1[N], d2[N]; //直径两个端点到所有点的距离
int n, m;

void dfs1(int u, int p, LL d, int w)
{
    if(d > maxdist)
    {
        ed = u;
        maxdist = d;
    }
    for(auto item : g[u])
    {
        int v = item.v, w = item.w;
        if(v == p) continue;
        dfs1(v, u, d + w, w);
    }
}

void dfs2(LL f[N], int u, int p, LL d)
{
    f[u] = d;
    for(auto item : g[u])
   {
         int v = item.v, w = item.w;
         if(v == p) continue;
         dfs2(f, v, u, d + w);
   }
}

int main()
{
    cin >> n >> m;
    while(m--)
    {
        int u, v, w;
        cin >> u >> v >> w;
        g[u].push_back({v, w});
        g[v].push_back({u, w});
    }

    st = 1;
    dfs1(st, 0, 0, 0);
    st = ed, maxdist = 0;
    dfs1(st, 0, 0, 0);
    dfs2(d1, st, 0, 0);
    dfs2(d2, ed, 0, 0);
    LL res = 0;
    for(int i = 1; i <= n; i++)
    {
        res = max(res, min(d1[i], d2[i]) + maxdist);
    }
    cout << res;
    return 0;
}

 

posted @ 2025-03-19 14:50  hackerchef  阅读(27)  评论(0)    收藏  举报