(题面来自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. Libevent库基础(1)

    1.创建 eevent_base struct event_base *base = event_base_new(); 2.创建 事件event struct event *ev; struct e ...

  2. java数据结构-04单循环链表

    单循环链表与单链表的不同是,单循环链表尾结点的next指向第一个结点(或头结点)  代码: 无头结点: public class SingleCircleLinkedList<E> ext ...

  3. python引用方法赋值问题探究

    python脚本编写中,经常会遇到引用一个模块的方法的场景.引用的方法里到底赋不赋值曾经困扰了我好久. 最近利用python写了一个接口自动化测试脚本,在查阅观看多篇博文和视频后解决了封装方法引用的问 ...

  4. java 文件和byte 互转

    /** * 获得指定文件的byte数组 */ private byte[] getBytes(String filePath){ byte[] buffer = null; try { File fi ...

  5. python机器学习TensorFlow框架

    TensorFlow框架 关注公众号"轻松学编程"了解更多. 一.简介 ​ TensorFlow是谷歌基于DistBelief进行研发的第二代人工智能学习系统,其命名来源于本身的运 ...

  6. pip install kaggle 出现 【网络不可达】?

    解决办法: pip install kaggle -i http://pypi.douban.com/simple --trusted-host pypi.douban.com

  7. 直播带货APP源码开发为什么选择云服务器

    云服务器可以为直播带货APP源码提供弹性计算以及更高的运行效率,避免资源浪费,随着直播带货APP源码业务需求的变化,可以实时扩展或缩减计算资源.CVM支持按实际使用的资源计费,可以节约计算成本. 一. ...

  8. 最长公共子串算法(Longest Common Substring)

    给两个字符串,求两个字符串的最长子串 (例如:"abc""xyz"的最长子串为空字符串,"abcde"和"bcde"的最 ...

  9. 总结distinct、group by 、row_number()over函数用法及区别

    distinct和group by 是一样的,查询去重,只能是全部重复的,也可以理解为针对单例,因为一行有一个字段不一样,他们就会认为这两行内容是不重复的.但是使用row_number()over这个 ...

  10. Linux杂谈: 实现一种简单实用的线程池(C语言)

    基本功能 1. 实现一个线程的队列,队列中的线程启动后不再释放: 2. 没有任务执行时,线程处于pending状态,等待唤醒,不占cpu: 3. 当有任务需要执行时,从线程队列中取出一个线程执行任务: ...