1
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
// 邻接表vector实现
struct node
{
int next;
};
vector <node> map[100005];
int vis_point[100005][9];
__int64 edge[100005][3];
int getpoint(node pp,node pp_not)
{
int i;
int point=pp.next;
int sum_point=0;
int notp=pp_not.next;
//把递归结果保存(判断点数时不用每次重新计算)
for (i=2;i<=8;i+=2)
{
if (vis_point[point][i-1]!=0 )
{
if (vis_point[point][i]==notp)
{
// printf("used memery\n");
return vis_point[point][i-1];
}
}
}
//
if (map[point].size()>1)
{
for (i=0;i<map[point].size();i++) ///遍历vector邻接表
{
if (notp!=map[point][i].next) //notp指的是每一个point点对应的not_point,指该point与notp点相连,去掉他们的边时,point所在的点集合的点的总数 ,在此称为单边亲属点数
sum_point+=getpoint(map[point][i],pp); //累计
}
}
else
{
return 1; //边缘点 返回1
}
return sum_point+1; //sum_point是由point递归得到的 单边亲属点数,因此 返回时要加上1代表自身
}
int main()
{
int i,j,kk,k,t,n,x,y;
__int64 w;
scanf("%d",&t);
for (kk=1;kk<=t;kk++)
{
scanf("%d",&n);
memset(vis_point,0,sizeof(vis_point));
for(i=1;i<=n-1;i++)
{
scanf("%d%d%I64d",&x,&y,&w);
edge[i][0]=x; //记录边信息
edge[i][1]=y;
edge[i][2]=w;
node a;
a.next=x;
map[y].push_back(a); //构建邻接表
a.next=y;
map[x].push_back(a);
}
__int64 sum=0;
for(i=1;i<=n-1;i++)
{
node a;
a.next=edge[i][0];
node b;
b.next=edge[i][1];
__int64 tmp=getpoint(a,b); //获取一条边的左点的单边亲属点数,记为x (则另一边的单边亲属点数为n-x)
for (j=2;j<=8;j+=2)
{
if ( vis_point[a.next][j]==0) //记录左点的单边亲属点 (由于一个点只能和4个点相连,因此记录下每一个点的四对 notp点与点边亲属点 )
{
vis_point[a.next][j]=b.next;
vis_point[a.next][j-1]=tmp;
break;
}
}
for (j=2;j<=8;j+=2)
{
if ( vis_point[b.next][j]==0) //记录右点的单边亲属点
{
vis_point[b.next][j]=a.next;
vis_point[b.next][j-1]=n-tmp;
break;
}
}
tmp=(n-tmp)*(tmp)*edge[i][2]; //经过该边的距离为 该边截断后 生成的两个点集的个数的积再乘以 边权
sum+=tmp; //累积
}
printf("Case %d: %I64d\n",kk,sum*2); //之前算的是
for(i=0;i<=n;i++) //vector清空
map[i].clear();
}
return 0;
}