#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=6e6+10;
#define int long long
int e[N],h[N],ne[N],w[N];
int idx;
int k;
inline int read()
{
int num=0, w=0;
char ch=0;
while (!isdigit(ch))
{
w|=ch=='-';
ch = getchar();
}
while (isdigit(ch))
{
num = (num<<3) + (num<<1) + (ch^48);
ch = getchar();
}
return w? -num: num;
}
void add(int a,int b,int c)
{
e[idx]=b;
w[idx]=c;
ne[idx]=h[a];
h[a]=idx++;
}
int dfs(int u,int fa,int &ans1,int &ans2)
{
int cnt=0;
for(int i=h[u]; i!=-1; i=ne[i])
{
int v=e[i];
if(v==fa)
continue;
int val=w[i];
int t=dfs(v,u,ans1,ans2);
cnt+=t;
//对于最小值,肯定是 能不经过 就不经过,如果连接这条边的两个子树的size 都是 偶数
//那么就 可以在子树中匹配,不用经过这条边
//如果是 存在奇数,那么就必然存在一对点,要经过这条边
if(t&1)
ans1+=val;
//对于最大值,肯定希望,多次利用,
//然后就看,被这条边分割成的两个子树的大小,最多有min(2*k-t,t) 对点,
//所以最多经过min(2*k-t,t)次
ans2+=min(2*k-t,t)*val;
}
return cnt+1;
}
void solve()
{
idx=0;
k=read();
for(int i=0;i<=2*k;i++)
h[i]=-1;
for(int i=1; i<=2*k-1; i++)
{
int a=read(),b=read(),c=read();
add(a,b,c);
add(b,a,c);
}
int ans1=0;
int ans2=0;
dfs(1,0,ans1,ans2);
cout<<ans1<<" "<<ans2<<endl;
}
signed main()
{
int t=read();
while(t--)
solve();
}