直径被定义为 一棵树上最长的简单路径

求直径长度

随机选一个点跑最短路,找到距离最大的任意一个点再跑一次最短路,找出距离最大的那个点

就是这棵树的直径

简单来说 就是两次dijk

参考代码:

    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<>> pq;
    vector<int> dist(n + 1, 1e18);
    dist[1] = 0;
    pq.emplace(0, 1);
    while (pq.size())
    {
        auto [w, u] = pq.top();
        pq.pop();
        if (w > dist[u])
        {
            continue;
        }
        for (auto [nxt, nxtw] : adj[u])
        {
            if (nxtw + w < dist[nxt])
            {
                dist[nxt] = w + nxtw;
                pq.emplace(dist[nxt], nxt);
            }
        }
    }
 
    int maxdist = -1;
    int d1;
    for (int i = 1; i <= n; i++)
    {
        if (dist[i] != 1e18)
        {
            if (dist[i] > maxdist)
            {
                maxdist = dist[i];
                d1 = i;
            }
        }
    }
 
    fill(all(dist), 1e18);
    dist[d1] = 0;
    pq.emplace(0, d1);
    while (pq.size())
    {
        auto [w, u] = pq.top();
        pq.pop();
        if (w > dist[u])
        {
            continue;
        }
        for (auto [nxt, nxtw] : adj[u])
        {
            if (nxtw + w < dist[nxt])
            {
                dist[nxt] = w + nxtw;
                pq.emplace(dist[nxt], nxt);
            }
        }
    }
 
    maxdist = -1;
    int d2;
    for (int i = 1; i <= n; i++)
    {
        if (dist[i] != 1e18)
        {
            if (dist[i] > maxdist)
            {
                maxdist = dist[i];
                d2 = i;
            }
        }
    }
 

求直径路径

在直径两个端点已经确定情况下 可以对 用一次 求得每一个节点在方向上的父节点 ,把所有的节点都存入 数组中,然后从d2开始遍历该数组即可获得路径

的这次 可以跟上面合并 降低常数

    vector<int> parent(n + 1, 0);
    function<void(int, int)> get_path_dfs = [&](int u, int p)
    {
        parent[u] = p;
        for (auto &[nxt, _] : adj[u])
        {
            if (nxt != p)
            {
                get_path_dfs(nxt, u);
            }
        }
    };
    get_path_dfs(d1, 0);
 
    vector<int> zhijing; // 直径
    for (int cur = d2; cur != 0; cur = parent[cur])
    {
        zhijing.push_back(cur);
    }
    reverse(all(zhijing));