(题面来自Luogu)

题目描述

聪聪和可可是兄弟俩,他们俩经常为了一些琐事打起来,例如家中只剩下最后一根冰棍而两人都想吃、两个人都想玩儿电脑(可是他们家只有一台电脑)……遇到这种问题,一般情况下石头剪刀布就好了,可是他们已经玩儿腻了这种低智商的游戏。

他们的爸爸快被他们的争吵烦死了,所以他发明了一个新游戏:由爸爸在纸上画n个“点”,并用n-1条“边”把这n个“点”恰好连通(其实这就是一棵树)。并且每条“边”上都有一个数。接下来由聪聪和可可分别随即选一个点(当然他们选点时是看不到这棵树的),如果两个点之间所有边上数的和加起来恰好是3的倍数,则判聪聪赢,否则可可赢。

聪聪非常爱思考问题,在每次游戏后都会仔细研究这棵树,希望知道对于这张图自己的获胜概率是多少。现请你帮忙求出这个值以验证聪聪的答案是否正确。

输入输出格式

输入格式:

输入的第1行包含1个正整数n。后面n-1行,每行3个整数x、y、w,表示x号点和y号点之间有一条边,上面的数是w。

输出格式:

以即约分数形式输出这个概率(即“a/b”的形式,其中a和b必须互质。如果概率为1,输出“1/1”)。

  用点分治统计从每个点u出发的路径,在cnt[k]中计数;其中k属于{0, 1, 2},表示该数组统计通过当前节点的长度%3等于k的路径数目。考虑将这些节点两两组合成长度%3等于0的路径:cnt[1]可以与cnt[2]两两组合,且题中给定的是有序点对,那么通过点u的满足条件的路径数ret += (cnt[2] * cnt[1] * 2)。cnt[0]可以两两组合,且可以重复,则ret += cnt[0] * cnt[0]。

代码:

 
  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <cctype>
  5. #define BUG puts("$$$")
  6. #define maxn 20010
  7. using namespace std;
  8. const int inf = 0x3f3f3f3f;
  9. int n;
  10. template <typename T>
  11. void read(T &x) {
  12. x = 0;
  13. char ch = getchar();
  14. int f = 1;
  15. while (!isdigit(ch)) {
  16. if (ch == '-') f = -1;
  17. ch = getchar();
  18. }
  19. while (isdigit(ch)) {
  20. x = x * 10 + (ch ^ 48);
  21. ch = getchar();
  22. }
  23. x *= f;
  24. }
  25. long long gcd(long long a, long long b) {
  26. if (!b) return a;
  27. return gcd(b, a % b);
  28. }
  29. int head[maxn], top;
  30. struct E {
  31. int to, nxt, w;
  32. } edge[maxn << 1];
  33. inline void insert(int u, int v, int w) {
  34. edge[++top] = (E) {v, head[u], w};
  35. head[u] = top;
  36. }
  37. int cnt[3];
  38. int size[maxn], Size, mn, root;
  39. bool vis[maxn];
  40. void find_rt(int u, int pre) {
  41. size[u] = 1;
  42. int son = 0;
  43. for (int i = head[u]; i; i = edge[i].nxt) {
  44. int v = edge[i].to;
  45. if (v == pre || vis[v]) continue;
  46. find_rt(v, u);
  47. size[u] += size[v];
  48. if (size[v] > size[son]) son = v;
  49. }
  50. int cur = max(size[son], Size - size[u]);
  51. if (cur < mn)
  52. mn = cur, root = u;
  53. }
  54. void dfs(int u, int pre, int depth, int val) {
  55. cnt[depth % 3] += val;
  56. for (int i = head[u]; i; i = edge[i].nxt) {
  57. int v = edge[i].to;
  58. if (v == pre || vis[v]) continue;
  59. dfs(v, u, depth + edge[i].w, val);
  60. }
  61. }
  62. long long solve(int u, int extra) {
  63. dfs(u, 0, extra, 1);
  64. long long ret = 1LL * cnt[1] * cnt[2] * 2 + 1LL * cnt[0] * cnt[0];
  65. dfs(u, 0, extra, -1);
  66. return ret;
  67. }
  68. long long ans;
  69. void divide(int u) {
  70. vis[u] = true;
  71. ans += solve(u, 0);
  72. int curSize = Size;
  73. for (int i = head[u]; i; i = edge[i].nxt) {
  74. int v = edge[i].to;
  75. if (vis[v]) continue;
  76. ans -= solve(v, edge[i].w);
  77. mn = inf, Size = size[u] > size[v] ? size[v] : curSize - size[u];
  78. find_rt(v, u);
  79. divide(root);
  80. }
  81. }
  82. int main() {
  83. read(n);
  84. int u, v, w;
  85. for (int i = 1; i < n; ++i) {
  86. read(u), read(v), read(w);
  87. insert(u, v, w), insert(v, u, w);
  88. }
  89. mn = inf, Size = n;
  90. find_rt(1, 0);
  91. divide(root);
  92. long long down = 1LL * n * n, k = gcd(down, ans);
  93. printf("%lld/%lld", ans / k, down / k);
  94. return 0;
  95. }

【P2634】聪聪可可——点分治的更多相关文章

  1. [bzoj2152][聪聪和可可] (点分治+概率)

    Description 聪聪和可可是兄弟俩,他们俩经常为了一些琐事打起来,例如家中只剩下最后一根冰棍而两人都想吃.两个人都想玩儿电脑(可是他们家只有一台电脑)……遇到这种问题,一般情况下石头剪刀布就好 ...

  2. bzoj2152 / P2634 [国家集训队]聪聪可可(点分治)

    P2634 [国家集训队]聪聪可可 淀粉质点分治板子 边权直接 mod 3 直接点分治统计出所有的符合条件的点对再和总方案数约分 至于约分.....gcd搞搞就好辣 #include<iostr ...

  3. 洛谷 P2634 [国家集训队]聪聪可可-树分治(点分治,容斥版) +读入挂+手动O2优化吸点氧才过。。。-树上路径为3的倍数的路径数量

    P2634 [国家集训队]聪聪可可 题目描述 聪聪和可可是兄弟俩,他们俩经常为了一些琐事打起来,例如家中只剩下最后一根冰棍而两人都想吃.两个人都想玩儿电脑(可是他们家只有一台电脑)……遇到这种问题,一 ...

  4. P2634 [国家集训队]聪聪可可(题解)(点分治)

    P2634 [国家集训队]聪聪可可(题解)(点分治) 洛谷题目 #include<iostream> #include<cstdlib> #include<cstdio& ...

  5. 模板—点分治A(容斥)(洛谷P2634 [国家集训队]聪聪可可)

    洛谷P2634 [国家集训队]聪聪可可 静态点分治 一开始还以为要把分治树建出来……• 树的结构不发生改变,点权边权都不变,那么我们利用刚刚的思路,有两种具体的分治方法.• A:朴素做法,直接找重心, ...

  6. AC日记——【模板】点分治(聪聪可可) 洛谷 P2634

    [模板]点分治(聪聪可可) 思路: 点分治: (感谢灯神) 代码: #include <bits/stdc++.h> using namespace std; #define maxn 2 ...

  7. 洛谷-P2634 [国家集训队]聪聪可可 点分治

    Description 聪聪和可可是兄弟俩,他们俩经常为了一些琐事打起来,例如家中只剩下最后一根冰棍而两人都想吃.两个人都想玩儿电脑(可是他们家只有一台电脑)……遇到这种问题,一般情况下石头剪刀布就好 ...

  8. 洛谷P2634 [国家集训队]聪聪可可 (点分治)

    题目描述 聪聪和可可是兄弟俩,他们俩经常为了一些琐事打起来,例如家中只剩下最后一根冰棍而两人都想吃.两个人都想玩儿电脑(可是他们家只有一台电脑)……遇到这种问题,一般情况下石头剪刀布就好了,可是他们已 ...

  9. 洛谷 P2634 BZOJ 2152 【模板】点分治(聪聪可可)

    题目描述 聪聪和可可是兄弟俩,他们俩经常为了一些琐事打起来,例如家中只剩下最后一根冰棍而两人都想吃.两个人都想玩儿电脑(可是他们家只有一台电脑)……遇到这种问题,一般情况下石头剪刀布就好了,可是他们已 ...

随机推荐

  1. win10 hyper-v的开启和关闭

    一.开启: 1. 控制面板->程序->启用或关闭Windows功能,Windows功能中勾选hyper-v功能 2. powershell中使用管理员权限运行下面的命令 bcdedit / ...

  2. OpenCascade拓扑对象之:Face的方向、参数域和曲面间的关系

    @font-face { font-family: "Times New Roman" } @font-face { font-family: "宋体" } @ ...

  3. [Luogu P2014]选课 (树形DP)

    题面 传送门:https://www.luogu.org/problemnew/show/P2014 Solution 这是一道十分经典的树形DP题,这种类型的树形DP有一种很普遍的解法. 首先,观察 ...

  4. DP百题练索引

    就是一篇还在咕的文章 DP百题练(一) DP百题练(二) DP百题练(三)

  5. python开发基础(二)运算符以及数据类型之bool(布尔值))

    # encoding: utf-8 # module builtins # from (built-in) # by generator 1.147 """ Built- ...

  6. 剑指Offer-Python(11-15)

    11.二进制中1的个数 链接:https://www.nowcoder.com/questionTerminal/8ee967e43c2c4ec193b040ea7fbb10b8?answerType ...

  7. 《精通Spring4.x企业应用开发实战》第三章

    这一章节主要介绍SpringBoot的使用,也是学习的重点内容,之后就打算用SpringBoot来写后台,所以提前看一下还是很有必要的. 3.SpringBoot概况 3.1.1SpringBoot发 ...

  8. 执行 yarn init报错,如何解决?

    安装yarn以后执行yarn init 命令来初始化项目 报错如下所示: 解决方法: 1.先用npm init初始化项目 在初始化的最后一步 is this ok(yes)? 输入yes回车后,可能会 ...

  9. 学习笔记——make项目中克隆GitHub目录失败的解决

    在示例项目中执行make后出现下面的错误 WARNING: Missing submodule components/json/cJSON... WARNING: Missing submodule ...

  10. 阅源-jdk8-FunctionalInterface注解

    package java.lang; import java.lang.annotation.*; /** * An informative annotation type used to indic ...