2152:聪聪可可(点分治)

链接

分析:

  点分治。

代码:

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<iostream>
 5 #include<cmath>
 6 
 7 using namespace std;
 8 const int INF = 2e9;
 9 const int N = 50010;
10 struct Edge{
11     int to,w,nxt;
12     Edge() {}
13     Edge(int a,int b,int c) {to = a,w = b,nxt = c;}
14 }e[100100];
15 int f[10],Ans,ans = INF,Sum,tot,Root;
16 int d[N],head[N],son[N];
17 bool vis[N];
18 
19 inline int read() {
20     int x = 0,f = 1;char ch=getchar();
21     for (; ch<'0'||ch>'9'; ch=getchar()) if(ch=='-')f=-1;
22     for (; ch>='0'&&ch<='9'; ch=getchar()) x=x*10+ch-'0';
23     return x*f;
24 }
25 inline void add_edge(int u,int v,int w) {
26     e[++tot] = Edge(v,w,head[u]);head[u] = tot;
27     e[++tot] = Edge(u,w,head[v]);head[v] = tot;
28 }
29 void getroot(int u,int fa) {
30     int cnt = 0;son[u] = 1;
31     for (int i=head[u]; i; i=e[i].nxt) {
32         int v = e[i].to;
33         if (v==fa || vis[v]) continue;
34         getroot(v,u);
35         son[u] += son[v];
36         cnt = max(cnt,son[v]);
37     }
38     cnt = max(cnt,Sum-son[u]); // son[u]以u为根的子树中,不包含u的所有的节点
39     if (cnt < ans) {ans = cnt;Root = u;}
40 }
41 void getdeep(int u,int fa) {
42     f[d[u]] ++;
43     for (int i=head[u]; i; i=e[i].nxt) {
44         int v = e[i].to;
45         if (v==fa || vis[v]) continue;
46         d[v] = (d[u]+e[i].w)%3;
47         getdeep(v,u);
48     }
49 }
50 int calcc(int x,int w) {
51     d[x] = w % 3;
52     f[0] = f[1] = f[2] = 0;
53     getdeep(x,0);
54     return f[1]*f[2]*2+f[0]*f[0];
55 }
56 void solve(int u) {
57     Ans += calcc(u,0);
58     vis[u] = true;
59     for (int i=head[u]; i; i=e[i].nxt) {
60         int v = e[i].to;
61         if (vis[v]) continue;
62         Ans -= calcc(v,e[i].w);
63         Sum = son[v];ans = INF;
64         getroot(v,0);
65         solve(Root);
66     }
67 }
68 int gcd(int a,int b) {
69     if (b==0) return a;
70     return gcd(b,a%b);
71 }
72 int main () {
73     int n = read();
74     for (int i=1; i<n; ++i) {
75         int u = read(),v = read(),w = read();
76         add_edge(u,v,w%3);
77     }
78     Sum = n;
79     getroot(1,0);
80     solve(Root);
81     if (Ans == 0) {
82         cout << "0/0";return 0;
83     }
84     int a = Ans,b = n*n,c = gcd(a,b);
85     cout << a/c << "/" << b/c;
86     return 0;
87 }
原文地址:https://www.cnblogs.com/mjtcn/p/8696734.html