这是一道点分治的模板题 但是一开始没有想到做法
题目要求的是满足树上两边相加等于3的情况 一开始有个很笨的思路 就是按i+=3去枚举 但是肯定超时
所以这道题其实是对树上距离%3 两边相加等于3的情况实际上是由模3后 为1 的边 乘上 模3后为2的边 其中可以互换 所以乘个2
再由sum[0]*sum[0] 包括了 0 3 , 3 0 ,3 3 ,0 0的情况 答案为这两个乘式的和
主要思想是模3 将来在树上用处应该很大
/*
luogu 2634
*/
#include <cstdio>
#include <cstring>
#include <queue>
#include <cmath>
#include <iostream>
#include <stack>
#include <set>
#include <map>
#include <sstream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int MAX_N = 30024;
int f[MAX_N],siz[MAX_N];
struct edge{
int next,v,dis;
}e[MAX_N<<1];
int eid,p[MAX_N],use[MAX_N],Siz,rt,cnt,d[MAX_N],k,sum[MAX_N];
long long ans;
inline int read()
{
int date = 0,m = 1;
char ch = 0;
while(ch!='-'&&(ch<'0'||ch>'9'))
ch = getchar();
if(ch=='-')
{
m = -1;
ch = getchar();
}
while(ch>='0' && ch<='9')
{
date = date*10+ch-'0';
ch = getchar();
}
return date*m;
}
inline void write(ll qw)
{
if(qw<0)
{
putchar('-');
qw = -qw;
}
if(qw>9)
write(qw/10);
putchar(qw%10+'0');
}
void init(){
memset(p,-1,sizeof(p));
memset(use,0,sizeof(use));
memset(d,0,sizeof(d));
rt = 0;
eid = 0;
}
void Insert(int u,int v,int dis){
e[eid].v = v;
e[eid].dis = dis;
e[eid].next = p[u];
p[u] = eid++;
}
void get_rt(int u,int fa){//u为当前点,fa为父亲节点
f[u] = 0, siz[u] = 1;//f表示这个点最大子树的大小,siz是这个点子树大小的和
for(int i = p[u];i!=-1;i = e[i].next){//枚举儿子
int y = e[i].v;
if(use[y]||y==fa) continue;//use表示之前遍历过了,这里没啥用
get_rt(y,u);//往下遍历
f[u] = max(f[u],siz[y]);//更新f
siz[u] += siz[y];
}
f[u] = max(f[u],Siz - siz[u]);//Siz表示在现在这棵子树中点的总数,开始时Siz=n,除了枚举的儿子所在的子树外,还有一棵子树是上面的那一堆,容斥原理
if(f[u]<f[rt]) rt = u;//更新root
}
void query(int u,int fa,int dis){
sum[dis%3]++;
for(int i = p[u];i!=-1;i=e[i].next){
int y = e[i].v;
if(use[y]||y==fa) continue;
query(y,u,(dis+e[i].dis)%3);
}
return;
}
long long solve(int u,int dis){
sum[0] = sum[1] = sum[2] = 0;
query(u,0,dis);
long long ans = 2ll*sum[1] * sum[2] + 1ll*sum[0]*sum[0];
return ans;
}
void dfs(int u){//Divide
use[u] = 1,ans+=solve(u,0);
for(int i = p[u];i!=-1;i=e[i].next){
int y = e[i].v;
if(use[y]) continue;
ans-=solve(y,e[i].dis);
Siz = siz[y],rt = 0;
get_rt(y,u),dfs(rt);
}
return ;
}
long long gcd(long long x,long long y)
{
return y==0 ? x:gcd(y,x%y);
}
int main(){
int n;
n = read();
init();
for(int i = 1;i<n;++i){
int a,b,dis;
a = read(),b = read(), dis = read()%3;
Insert(a,b,dis);
Insert(b,a,dis);
}
f[rt] = Siz = n;
get_rt(1,0);
dfs(rt);
long long x = n* n;
long long tmp = gcd(ans,n*n);
ans/=tmp;
x/=tmp;
printf("%lld/%lld\n",ans,x);
return 0;
}