P2634 [国家集训队]聪聪可可
淀粉质
第二道点分治的题
关于点分治的一点理解:
所谓点分治,其实就是把要求的问题(一般与路径有关)划分成两种情况
1.路径经过rt(根节点)
2.路径在根节点的子树内
我们只需要处理情况1,因为情况2就是情况1的递归子问题
在这个过程中,要注意容斥原理的应用;
//--------------------------------------------------------------------------
关于此题:
w可预先%3(不会影响答案),注意乘法原理的应用;
1 #include<cstdio> 2 #include<cmath> 3 #include<cstring> 4 #include<algorithm> 5 #include<iostream> 6 using namespace std; 7 #define up(i,l,r) for(register int i = (l); i <= (r); ++i) 8 #define dn(i,l,r) for(register int i = (l); i >= (r); --i) 9 #define ll long long 10 #define re register 11 using namespace std; 12 13 template <typename T> void in(T &x) { 14 x = 0; T f = 1; char ch = getchar(); 15 while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();} 16 while( isdigit(ch)) {x = 10 * x + ch - 48; ch = getchar();} 17 x *= f; 18 } 19 20 template <typename T> void out(T x) { 21 if(x < 0) x = -x , putchar('-'); 22 if(x > 9) out(x/10); 23 putchar(x%10 + 48); 24 } 25 //--------------------------------------------------------- 26 27 const int N = 20007; 28 29 int n; 30 ll ans = 0; 31 32 struct edge { 33 int v,w,nxt; 34 }e[N<<1];int tot,head[N]; 35 36 void add(int u,int v,int w) { 37 e[++tot].v = v; 38 e[tot].w = w; 39 e[tot].nxt = head[u]; 40 head[u] = tot; 41 } 42 43 //--------------------------------------------------------- 44 45 bool vis[N]; 46 int size[N],f[N]; 47 int Tsize,rt,dis[N]; 48 int t[3]; 49 50 void get_rt(int u,int fa) { 51 size[u] = 1; f[u] = 0; 52 for(re int i = head[u]; i ;i = e[i].nxt) { 53 int v = e[i].v; if(v == fa || vis[v]) continue; 54 get_rt(v,u); size[u] += size[v]; 55 f[u] = max(f[u],size[v]); 56 } 57 f[u] = max(f[u],Tsize-size[u]); 58 if(f[u] < f[rt]) rt = u; 59 } 60 61 void get_dis(int u,int fa) { 62 ++t[dis[u]%3]; 63 for(re int i = head[u]; i ;i = e[i].nxt) { 64 int v = e[i].v; if(v == fa || vis[v]) continue; 65 dis[v] = (dis[u]+e[i].w)%3; get_dis(v,u); 66 } 67 } 68 69 ll calc(int u) { 70 t[0] = t[1] = t[2] = 0; 71 get_dis(u,0); 72 return t[0]*t[0]+2*t[1]*t[2]; 73 } 74 75 void solve(int u) { 76 vis[u] = 1; dis[u] = 0; 77 ans += calc(u); 78 for(re int i = head[u]; i ;i = e[i].nxt) { 79 int v = e[i].v; if(vis[v]) continue; 80 dis[v] = e[i].w; 81 ans -= calc(v); 82 Tsize = size[v],rt = 0,f[0] = n+1; 83 get_rt(v,0); solve(rt); 84 } 85 } 86 87 void init() { 88 memset(head,0,sizeof(head)); 89 memset(vis,0,sizeof(vis)); 90 ans = 0; Tsize = n,rt = 0,f[0] = n+1; 91 } 92 93 ll Gcd(ll a,ll b) {return b == 0 ? a:Gcd(b,a%b);} 94 95 int main() { 96 init(); 97 in(n); int x,y,w; 98 up(i,1,n-1) { 99 in(x); in(y); in(w); add(x,y,w%3),add(y,x,w%3); 100 //技巧 mod 3 101 } 102 get_rt(1,0); solve(rt); 103 ll gcd = Gcd(ans,1ll*n*n); 104 out(ans/gcd); putchar('/'); out(1ll*n*n/gcd); 105 return 0; 106 }