solution

经典的方式。

转化一下题意就是:选一个根,使得所有叶子节点到该节点路径上最小边权之和最大。

先考虑的做法

表示以1为根时i这棵子树内的答案。那么就有

所以枚举一下根,然后每次这样dfs一遍,就可以在时间内解决问题了。

考虑优化该算法

我们只要在以1为根做一遍上面自下而上的dp之后,在做一遍自上而下的dp就可以转移出以任何一个点为根时的答案。
转移方程就是:表示在自下而上的dp过程中,v对于u的贡献。

code

/*
* @Author: wxyww
* @Date: 2020-04-12 20:30:52
* @Last Modified time: 2020-04-12 20:43:48
*/
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<bitset>
#include<cstring>
#include<algorithm>
#include<string>
#include<queue>
#include<vector>
using namespace std;
typedef long long ll;
const int N = 200010;
ll read() {
    ll x=0,f=1;char c=getchar();
    while(c<'0'||c>'9') {
        if(c=='-') f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9') {
        x=x*10+c-'0';
        c=getchar();
    }
    return x*f;
}
struct node {
    int v,nxt;ll w;
}e[N << 1];
int head[N],ejs;
void add(int u,int v,int w) {
    e[++ejs].v = v;e[ejs].w = w;e[ejs].nxt = head[u];head[u] = ejs;
}
ll f[N];
void dfs1(int u,int fa) {
    for(int i = head[u];i;i = e[i].nxt) {
        int v = e[i].v;
        if(v == fa) continue;
        dfs1(v,u);
        f[u] += min(e[i].w,f[v]);
    }
    if(!f[u]) f[u] = 1e14;
}
void dfs2(int u,int fa) {
    for(int i = head[u];i;i = e[i].nxt) {
        int v = e[i].v;
        if(v == fa) continue;
        f[v] += min(e[i].w,f[u] - min(f[v],e[i].w));
        dfs2(v,u);
    }
}
int main() {
    int T = read();

    while(T--) {
        int n = read();
        memset(head,0,sizeof(head));
        ejs = 0;
        for(int i = 1;i < n;++i) {
            int u = read(),v = read(),w = read();
            add(u,v,w);add(v,u,w);
        }
        memset(f,0,sizeof(f));
        dfs1(1,0);
        dfs2(1,0);
        ll ans = 0;
        for(int i = 1;i <= n;++i) {
            if(f[i] > 1e13) continue;
            ans = max(ans,f[i]);
            // printf("%lld ",f[i]);
        }
        // puts("");
        cout<<ans<<endl;
    }

    return 0;
}