[关闭]
@wsndy-xx 2018-05-09T21:31:56.000000Z 字数 1630 阅读 877

Luogu [国家集训队]聪聪可可

题解


点分治 / 树形dp
这里用点分解决
我们不需要记录真是的dis[], 只需使用 dis[] % 3 后的值
那么只需要这样传参数

  1. void Getdis(u fa, len % 3) {;}

表示: js[i] 表示 dis[] % 3 == i 的个数
那么怎么统计 Answer 呢??
我们考虑 js[0]Answer 的贡献为 js[0] * js[0]
这是显然的
对于 js[1] 和 js[2] 发现 (js[1] + js[2]) % 3 == 0,
满足条件
所以 js[1], js[2]Answer 的贡献为 js[1] * js[2] * 2
所以 Answer += js[1] * js[2] * 2 + js[0] * js[0];

Code

  1. #include <bits/stdc++.h>
  2. const int N = 2e4 + 10;
  3. int n, now = 1, head[N], dis[N];
  4. struct Node {int v, w, nxt;} G[N << 1];
  5. int size[N], maxson[N], Root;
  6. bool vis[N];
  7. int js[N];
  8. int Answer;
  9. int Size;
  10. #define gc getchar()
  11. inline int read() {
  12. int x = 0; char c = gc;
  13. while(c < '0' || c > '9') c = gc;
  14. while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = gc;
  15. return x;
  16. }
  17. inline void Add(int u, int v, int w) {G[now].v = v; G[now].w = w; G[now].nxt = head[u]; head[u] = now ++;}
  18. void Getroot(int u, int fa) {
  19. size[u] = 1;
  20. maxson[u] = 0;
  21. for(int i = head[u]; ~ i; i = G[i].nxt) {
  22. int v = G[i].v;
  23. if(vis[v] || v == fa) continue ;
  24. Getroot(v, u);
  25. size[u] += size[v];
  26. maxson[u] = std:: max(maxson[u], size[v]);
  27. }
  28. maxson[u] = std:: max(maxson[u], Size - size[u]);
  29. if(maxson[u] < maxson[Root]) Root = u;
  30. }
  31. void Getdis(int u, int fa, int len) {
  32. dis[u] = len; js[dis[u]] ++;
  33. for(int i = head[u]; ~ i; i = G[i].nxt) {
  34. int v = G[i].v;
  35. if(vis[v] || v == fa) continue ;
  36. Getdis(v, u, (len + G[i].w) % 3);
  37. }
  38. }
  39. int Calc(int u, int len) {
  40. js[0] = js[1] = js[2] = 0;
  41. Getdis(u, 0, len % 3);
  42. return js[1] * js[2] * 2 + js[0] * js[0];
  43. }
  44. void Getans(int u) {
  45. vis[u] = 1;
  46. Answer += Calc(u, 0);
  47. for(int i = head[u]; ~ i; i = G[i].nxt) {
  48. int v = G[i].v;
  49. if(vis[v]) continue ;
  50. Answer -= Calc(v, G[i].w);
  51. Root = 0;
  52. Size = size[v];
  53. Getroot(v, u);
  54. Getans(Root);
  55. }
  56. }
  57. int Gcd(int a, int b) {
  58. return b == 0 ? a : Gcd(b, a % b);
  59. }
  60. int main() {
  61. n = read();
  62. for(int i = 1; i <= n; i ++) head[i] = -1;
  63. for(int i = 1; i < n; i ++) {
  64. int u = read(), v = read(), w = read();
  65. Add(u, v, w), Add(v, u, w);
  66. }
  67. maxson[Root] = n;
  68. Size = n;
  69. Getroot(1, 0);
  70. Getans(Root);
  71. int gcd = Gcd(Answer, n * n);
  72. std:: cout << Answer / gcd << "/" << n * n / gcd << "\n";
  73. return 0;
  74. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注