传送门

思路:要求找一个最小Gg值,当 K = 1 时,我们知道这个点一定在直径上面,要使 Gg 最小,则该点到直径的两个端点距离的最大值最小。

DFS求直径:随意找一个点为起点,距离这个点最远的点就是直径的一个端点S,然后在以S为起点DFS,距离S距离最远的点就是直径的另一个端点E。

我们要记录一个结点的dp值  dp [ i ] 表示以 i 为根结点的子树上的所有结点距离 father[ i ] 的最大值。
以树的中心为起点,我们利用优先队列进行 K 次出队列的操作,最后队列顶端的 dp 值就是答案,如果不存在答案即为0。

代码:

///#include<bits/stdc++.h>
///#include<unordered_maps>
///#include<unordered_set>
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<bitset>
#include<set>
#include<stack>
#include<map>
#include<list>
#include<new>
#include<vector>

#define MT(a, b) memset(a,b,sizeof(a));
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double pai = acos(-1.0);
const double E = 2.718281828459;
const int mod = 20190414;
const ll INF = 0x3f3f3f3f3f3f;

int t, n, k;

struct node {
    int e;
    ll c;
    int p;

    bool friend operator<(node a, node b) {
        return a.c < b.c;
    }
} load[200005];

int head[100005], sign;

void add_edge(int s, int e, ll c) {
    load[++sign] = node{e, c, head[s]};
    head[s] = sign;
}

ll maxn;
int des, start;
int father[100005];
ll dis[100005];

void dfs(int s, int pre) {
    if (dis[s] > maxn) {
        des = s;
        maxn = dis[s];
    }
    for (int i = head[s], e; ~i; i = load[i].p) {
        e = load[i].e;
        if (e ^ pre) {
            father[e] = s;
            dis[e] = dis[s] + load[i].c;
            dfs(e, s);
        }
    }
}

int get_point() {
    /// start 起点  des 终点
    maxn = 0;
    father[1] = -1;
    start = 1;
    dis[1] = 0;
    dfs(1, -1);

    start = des;
    maxn = 0;
    father[start] = -1;
    dis[start] = 0;
    dfs(start, -1);

    ll minn = INF;
    int point, x = des;
    while (x != -1) {
        maxn = max(dis[x], dis[des] - dis[x]);
        if (maxn < minn) {
            minn = maxn;
            point = x;
        }
        x = father[x];
    }
    return point;
}

ll max_dis[100005];
bool vis[100005];


ll dfs_len(int s, int pre) {
    //max_dis[s] = 0;
    ll ans = 0;
    for (int i = head[s], e; ~i; i = load[i].p) {
        e = load[i].e;
        if (e ^ pre) {
            ll temp = dfs_len(e, s) + load[i].c;
            ans = max(ans, temp);
            max_dis[e] = temp;
        }
    }
    return ans;
}

int main() {
    scanf("%d", &t);
    while (t--) {
        int s, e;
        ll c;
        scanf("%d %d", &n, &k);
        sign = 0;
        for (int i = 1; i <= n; i++) {
            vis[i] = 0;
            head[i] = -1;
        }
        for (int i = 1; i < n; i++) {
            scanf("%d %d %lld", &s, &e, &c);
            add_edge(s, e, c);
            add_edge(e, s, c);
        }
        int point = get_point();
        dfs_len(point, -1);
        priority_queue<node> q;
        q.push(node{point, max_dis[point], 0});
        vis[point] = 1;
        for (int i = 1; i <= k; i++) {
            node w = q.top();
            q.pop();
            for (int j = head[w.e]; ~j; j = load[j].p) {
                e = load[j].e;
                if (!vis[e]) {
                    q.push(node{e, max_dis[e], 0});
                    vis[e] = 1;
                }
            }
        }
        if (q.empty()) {
            printf("0\n");
        } else {
            printf("%lld\n", q.top().c);
        }
    }
}