(题面来自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. 关于transition中嵌套keep-alive的问题解决

    需求:在使用keep-alive的同时使用transition动画效果 最开始是这样写的,但是发现报错,而且动画效果失效 <transition name="container-rig ...

  2. Redis常用命令(5)——Set

    SADD 格式:SADD key member [member ...] 作用:在集合key中插入一个或多个元素.如果member已经存在,则忽略member.如果key不存在则先创建集合key. 返 ...

  3. Java学习的第三十五天

    1. 例1.1 例1.2 例1.3 例1.4 2.不知道为什么con的时候错误需要加入 3.明天继续写例题

  4. curl 錯誤碼

    CURL状态码列表 状态码 状态原因 解释 0 正常访问 1 错误的协议 未支持的协议.此版cURL 不支持这一协议. 2 初始化代码失败 初始化失败. 3 URL格式不正确 URL 格式错误.语法不 ...

  5. AMA指标原作者Perry Kaufman 100+套交易策略源码分享

    更多精彩内容,欢迎关注公众号:数量技术宅.想要获取本期分享的完整策略代码,请加技术宅微信:sljsz01 AMA技术指标与原作者 Kaufman 说起 Perry Kaufman 这个名字,不少读者会 ...

  6. leetcode1Minimum Depth of Binary Tree

    题目描述 求给定二叉树的最小深度.最小深度是指树的根结点到最近叶子结点的最短路径上结点的数量. Given a binary tree, find its minimum depth.The mini ...

  7. leetcode17gas-station

    题目描述 环形路上有n个加油站,第i个加油站的汽油量是gas[i]. 你有一辆车,车的油箱可以无限装汽油.从加油站i走到下一个加油站(i+1)花费的油量是cost[i],你从一个加油站出发,刚开始的时 ...

  8. 【故障公告】博客站点再次出现故障,最终回退 .NET 5.0 恢复正常

    自从博客系统升级 .NET 5.0 之后遇到的诡异故障(一.二.三.四),今天它又出现了,就在前天刚刚故障之后, 就在昨天 .NET 5.0 正式版刚刚发布之后,出现了. 今天晚上我们在 19:30 ...

  9. pandas_01

    # Pandas 知识点总结 # Pandas数据结构:Series 和 DataFrame import pandas as pd import numpy as np # 一,Series: # ...

  10. .NET5都来了,你还不知道怎么部署到linux?最全部署方案,总有一款适合你

    随着2020进入4季度,.NET5正式版也已经与大家见面了.不过,尽管 .NET Core发布已经有四五年的时间,但到目前为止,依旧有很多.NET开发者在坚守者.NET4,原因不尽相同,但最大的问题可 ...