#include<cstdio> #include<cstring> #define INF 0x7fffffff using namespace std; const int N=2e5+5; inline int min(int a,int b){ return (a<b?a:b); } int first[N],next[N*2],to[N*2],c[N*2],n; int edge_count=0; inline void add(int x,int y,int w){ edge_count++; to[edge_count]=y; c[edge_count]=w; next[edge_count]=first[x]; first[x]=edge_count; } int f[N][2]; long long ans=0; //f[i][1]->以i结点为根的子树 向下流动 的最大流量 //f[i][2]->以i节点为根的子树 向上流动 的最大流量 void search(int root,int fa){ if(to[ first[root] ]==fa){ //错因分析:本想判断root结点是否为叶节点,但是存在那样一个结点NODE s.t. first【root】->father
//so, it should be 【 if(to[ first[root] ]==fa && !next[ first[root] ]) 】
f[root][0]=INF; return; } for(int i=first[root];i;i=next[i]){ if(to[i]==fa)continue; search(to[i],root); f[root][0]+=min(f[ to[i] ][0],c[i]); //printf("root:%d",root);printf(" %d\n",f[root][0]); } } void dfs(int root,int fa){ for(int i=first[root];i;i=next[i]){ if(to[i]==fa){ f[root][1]=min(c[i],f[fa][1]+f[fa][0]-min(c[i],f[root][0])); } } for(int i=first[root];i;i=next[i]){ if(to[i]==fa)continue; dfs(to[i],root); } long long t=0ll; if(f[root][1]!=(INF>>1) )t+=f[root][1]; if(f[root][0]!=INF)t+=f[root][0]; if(ans<t)ans=t; } int aa; int main() { //freopen("degree.in","r",stdin); //freopen("degree.out","w",stdout); scanf("%d",&aa); for(int k=1;k<=aa;k++){ memset(first,0,sizeof(first)); memset(next,0,sizeof(next)); memset(to,0,sizeof(to)); memset(c,0,sizeof(c)); memset(f,0,sizeof(f)); ans=0ll; edge_count=0; scanf("%d",&n); for(int i=1,a,b,w;i<n;++i){ scanf("%d%d%d",&a,&b,&w); add(a,b,w); add(b,a,w); } search(1,0); if(!next[ first[1] ])f[1][1]=INF>>1; dfs(1,0); printf("%lld\n",ans); } return 0; }