【BZOJ 2152】 聪聪可可
【题目链接】
https://www.lydsy.com/JudgeOnline/problem.php?id=2152
【算法】
点分治
【代码】
#include<bits/stdc++.h> using namespace std; #define MAXN 20010 int i,n,u,v,w,ans1,ans2,g,tot,len,root; int head[MAXN],size[MAXN],weight[MAXN],d[MAXN],sum[MAXN]; bool visited[MAXN]; struct Edge { int to,w,nxt; } e[MAXN<<1]; inline int gcd(int x,int y) { if (y == 0) return x; else return gcd(y,x % y); } inline void addedge(int u,int v,int w) { tot++; e[tot] = (Edge){v,w,head[u]}; head[u] = tot; } inline void getroot(int u,int fa,int total) { int i,v; size[u] = 1; weight[u] = 0; for (i = head[u]; i; i = e[i].nxt) { v = e[i].to; if (v != fa && !visited[v]) { getroot(v,u,total); size[u] += size[v]; weight[u] = max(weight[u],size[v]); } } weight[u] = max(weight[u],total - size[u]); if (weight[u] < weight[root]) root = u; } inline void dfs(int u,int fa) { int i,v,w; d[++len] = sum[u]; for (i = head[u]; i; i = e[i].nxt) { v = e[i].to; w = e[i].w; if (v != fa && !visited[v]) { sum[v] = (sum[u] + w) % 3; dfs(v,u); } } } inline int calc(int u) { int i; int ret = 0; int cnt[3]; memset(cnt,0,sizeof(cnt)); len = 0; dfs(u,0); for (i = 1; i <= len; i++) cnt[d[i]]++; for (i = 1; i <= len; i++) ret += cnt[(3 - d[i]) % 3]; return ret; } inline void work(int u) { int i,v,w; visited[u] = true; sum[u] = 0; ans1 += calc(u); for (i = head[u]; i; i = e[i].nxt) { v = e[i].to; w = e[i].w; if (!visited[v]) { sum[v] = w % 3; ans1 -= calc(v); root = 0; getroot(v,0,size[v]); work(root); } } } int main() { scanf("%d",&n); for (i = 1; i < n; i++) { scanf("%d%d%d",&u,&v,&w); addedge(u,v,w); addedge(v,u,w); } memset(visited,false,sizeof(visited)); size[0] = weight[0] = n; getroot(1,0,n); ans1 = 0; ans2 = n * n; work(root); g = gcd(ans1,ans2); ans1 /= g; ans2 /= g; printf("%d/%d\n",ans1,ans2); return 0; }