2152: 聪聪可可

Time Limit: 3 Sec  Memory Limit: 259 MB
Submit: 3435  Solved: 1776
[Submit][Status][Discuss]

Description

聪聪和可可是兄弟俩,他们俩经常为了一些琐事打起来,例如家中只剩下最后一根冰棍而两人都想吃、两个人都想玩儿电脑(可是他们家只有一台电脑)……遇到这种问题,一般情况下石头剪刀布就好了,可是他们已经玩儿腻了这种低智商的游戏。他们的爸爸快被他们的争吵烦死了,所以他发明了一个新游戏:由爸爸在纸上画n个“点”,并用n-1条“边”把这n个“点”恰好连通(其实这就是一棵树)。并且每条“边”上都有一个数。接下来由聪聪和可可分别随即选一个点(当然他们选点时是看不到这棵树的),如果两个点之间所有边上数的和加起来恰好是3的倍数,则判聪聪赢,否则可可赢。聪聪非常爱思考问题,在每次游戏后都会仔细研究这棵树,希望知道对于这张图自己的获胜概率是多少。现请你帮忙求出这个值以验证聪聪的答案是否正确。

Input

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

Output

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

Sample Input

5
1 2 1
1 3 2
1 4 1
2 5 3

Sample Output

13/25
【样例说明】
13组点对分别是(1,1) (2,2) (2,3) (2,5) (3,2) (3,3) (3,4) (3,5) (4,3) (4,4) (5,2) (5,3) (5,5)。

【数据规模】
对于100%的数据,n<=20000。

HINT

Source

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2152

一道裸的树分治

令节点 i 到当前分治的节点的距离为 dis[i] ,对于任意一个满足条件的点对 [i,j] ,有 (dis[i] + dis[j]) % 3 = 0

我们将所有点的 dis[] 值对 3 取余,统计出取余后结果为 0,1,2 的个数,记为 num[0], num[1], num[2]。

那么,对于子树中任意的一个节点 i :

1)dis[i] % 3 = 0 时:当前符合条件的点对数为 num[0](即同为 3 的倍数);

2)dis[i] % 3 = 1 时:当前符合条件的点对数为 num[3 - 1 = 2] 。

(证明:将 dis[i] 拆成 3x + 1,满足条件的另一个点的距离 dis[j] 拆成 3y + 2,则和为 3x + 1 + 3y + 2 = 3x + 3y + 3 = 3(x + y + 1),是 3 的倍数)

3)dis[i] % 3 = 2 时:当前符合条件的点对数为 num[3 - 2 = 1] 。(证明同上)

以上情况可合并为 cnt += (!dis[i] ? num[0] : num[3 - dis[i]])(cnt 为记录的答案,dis[i] 已经对 3 取余过)

下面给出AC代码:

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. inline int read()//读入优化
  4. {
  5. int x=,f=;//f表示符号,x表示首位数字0
  6. char ch=getchar();
  7. while(ch<''||ch>'')//如果ch不是数字
  8. {
  9. if(ch=='-')//如果是符号就改变符号
  10. f=-;
  11. ch=getchar();
  12. }
  13. while(ch>=''&&ch<='')//如果ch是数字,接下来的每位数字
  14. {
  15. x=x*+ch-'';//将数字添加进x内
  16. ch=getchar();
  17. }
  18. return x*f;//返回数值
  19. }
  20. inline void write(int x)//输出优化
  21. {
  22. if(x<)//判断小于0的情况
  23. {
  24. putchar('-');
  25. x=-x;
  26. }
  27. if(x>)//保存每一位
  28. {
  29. write(x/);
  30. }
  31. putchar(x%+'');//输出
  32. }
  33. inline int gcd(int a,int b)//求最大公因数
  34. {
  35. return b==?a:gcd(b,a%b);
  36. }
  37. const int N=;
  38. int last[N];
  39. int son[N];//son表示树的大小
  40. int f[N];//表示最大子树的节点数
  41. int d[N];//表示到k的距离
  42. int t[N];//表示到k的距离%3=0的点的个数
  43. bool vis[N];
  44. struct Edge//前向星存边
  45. {
  46. int to,next,v;
  47. }edge[N<<];//保存双向图
  48. int n,cnt,ans,root,sum;
  49. inline void addage(int u,int v,int w)//连双向边
  50. {
  51. edge[++cnt].to=v;
  52. edge[cnt].next=last[u];
  53. last[u]=cnt;
  54. edge[cnt].v=w;
  55. edge[++cnt].to=u;
  56. edge[cnt].next=last[v];
  57. last[v]=cnt;
  58. edge[cnt].v=w;
  59. }
  60. inline void getroot(int x,int fa)//寻找根节点,根节点满足最大儿子子树规模最小,求重心的操作
  61. {
  62. son[x]=;//son[x]表示x的树大小
  63. f[x]=;//f[x]表示x最大子树的节点数
  64. for(int i=last[x];i;i=edge[i].next)//枚举和x相邻的每一个点
  65. {
  66. if(!vis[edge[i].to]&&edge[i].to!=fa)//如果没有被删除,并且当前节点不是根节点
  67. {
  68. getroot(edge[i].to,x);
  69. son[x]+=son[edge[i].to];//子树规模
  70. f[x]=max(f[x],son[edge[i].to]);
  71. }
  72. }
  73. f[x]=max(f[x],sum-son[x]);//x最大子树的节点数f[x]=max(f[x],与此子树大小-f[x])
  74. if(f[x]<f[root])
  75. root=x;
  76. }
  77. inline void getdeep(int x,int fa)//获得每个点到cal中的x的距离,即root
  78. {
  79. t[d[x]]++;//统计到k距离的个数,//将对应余数的数目+1
  80. for(int i=last[x];i;i=edge[i].next)//枚举和x相邻的每一个点
  81. {
  82. if(!vis[edge[i].to]&&edge[i].to!=fa)//如果没有被删除,并且当前节点不是根节点
  83. {
  84. d[edge[i].to]=(d[x]+edge[i].v)%;
  85. getdeep(edge[i].to,x);
  86. }
  87. }
  88. }
  89. inline int cal(int x,int now)//t[0]表示到k的距离%3=0的点的个数,t[1]表示余数为1,t[2]表示余数为2,所以计算方案数时,t[0]内部解决,t[1]和t[2]两两搭配
  90. {
  91. t[]=t[]=t[]=;//余数清0
  92. d[x]=now;
  93. getdeep(x,);//getdeep更新子树的root的值,计算深度root
  94. return t[]*t[]*+t[]*t[];//计算路径数
  95. }
  96. inline void work(int x)//表示work以x为根的子树,此时x已经是重心
  97. {
  98. ans+=cal(x,);//统计不同子树通过重心的个数
  99. vis[x]=;//把x从树中删除
  100. for(int i=last[x];i;i=edge[i].next)//枚举和x相邻的每一个点
  101. {
  102. if(!vis[edge[i].to])//如果没有被删除,说明在某一棵子树中
  103. {
  104. ans-=cal(edge[i].to,edge[i].v);//去除在同一个子树中被重复统计的
  105. root=;
  106. sum=son[edge[i].to];
  107. getroot(edge[i].to,);//找到所在子树的重心root,更新重心root
  108. work(root);//递归处理root,求解子树
  109. }
  110. }
  111. }
  112. int main()
  113. {
  114. n=read();
  115. for(int i=;i<n;i++)//建图
  116. {
  117. int u=read();
  118. int v=read();
  119. int w=read()%;
  120. addage(u,v,w);//建立一个无向图
  121. }
  122. f[]=n;
  123. sum=n;
  124. getroot(,);
  125. work(root);
  126. int t=gcd(ans,n*n);
  127. printf("%d/%d\n",ans/t,n*n/t);
  128. return ;
  129. }

洛谷 2634&&BZOJ 2152: 聪聪可可【点分治学习+超详细注释】的更多相关文章

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

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

  2. 【BZOJ 2152】 聪聪可可

    [题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=2152 [算法] 点分治 [代码] #include<bits/stdc++.h ...

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

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

  4. 洛谷 P3307: bzoj 3202: [SDOI2013] 项链

    题目传送门:洛谷P3307.这题在bzoj上是权限题. 题意简述: 这题分为两个部分: ① 有一些珠子,每个珠子可以看成一个无序三元组.三元组要满足三个数都在$1$到$m$之间,并且三个数互质,两个珠 ...

  5. 洛谷 4106 / bzoj 3614 [HEOI2014]逻辑翻译——思路+类似FWT

    题目:https://www.luogu.org/problemnew/show/P4106 https://www.lydsy.com/JudgeOnline/problem.php?id=3614 ...

  6. 洛谷 P3332 BZOJ 3110 [ZJOI2013]K大数查询

    题目链接 洛谷 bzoj 题解 整体二分 Code #include<bits/stdc++.h> #define LL long long #define RG register usi ...

  7. 洛谷 P2486 BZOJ 2243 [SDOI2011]染色

    题目描述 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221” ...

  8. 洛谷 P2827 BZOJ 4721 UOJ #264 蚯蚓

    题目描述 本题中,我们将用符号表示对c向下取整,例如:. 蛐蛐国最近蚯蚓成灾了!隔壁跳蚤国的跳蚤也拿蚯蚓们没办法,蛐蛐国王只好去请神刀手来帮他们消灭蚯蚓. 蛐蛐国里现在共有n只蚯蚓(n为正整数).每只 ...

  9. 洛谷 P2155 BZOJ 2186 codevs 2301 [SDOI2008]沙拉公主的困惑

    题目描述 大富翁国因为通货膨胀,以及假钞泛滥,政府决定推出一项新的政策:现有钞票编号范围为1到N的阶乘,但是,政府只发行编号与M!互质的钞票.房地产第一大户沙拉公主决定预测一下大富翁国现在所有真钞票的 ...

随机推荐

  1. JMeter循环控制器循环次数使用变量控制注意事项

    1.进入循环控制器之前变量要有值: 2.BeanShell处理文件,读取行数,赋值给变量,要有相应的Sampler,不然脚本不会运行. 对于单个线程来说,假如设置了循环2次,线程启动后,运行结束,此时 ...

  2. ubuntu16.04 查询ip,网关,dns信息

    用ifconfig命令只能查询ip,子网掩码信息,不能获取dns和网关信息 用下面命令即可查询 nmcli dev show

  3. c# 了解c# 面向对象

    C#是微软公司发布的一种面向对象的.运行于.NET Framework之上的高级程序设计语言.并定于在微软职业开发者论坛(PDC)上登台亮相.C#是微软公司研究员Anders Hejlsberg的最新 ...

  4. Mysql 索引优化分析

    MySQL索引优化分析 为什么你写的sql查询慢?为什么你建的索引常失效?通过本章内容,你将学会MySQL性能下降的原因,索引的简介,索引创建的原则,explain命令的使用,以及explain输出字 ...

  5. 正则表达过滤表单隐藏元素,组装post数据

    <form name="form1" action="'.$serverUrl.'" method="post" > <i ...

  6. flask连接sqlalchemy数据库,实现简单的登录跳转功能

    环境:python2.7 python库:flask,flask_wtf,wtforms,sqlalchemy 原理:运行app-连接数据库-打开登录页面-输入登录信息(错误->提示错误信息:正 ...

  7. Yii 框架学习--03 多应用多模块

    本文以YII 2.0.7为例. 概述 首先看看多应用和多模块的特点: 多应用的特点: 独立配置文件 独立域名 多模块的特点: 统一配置文件 统一域名 那么,实际该怎么决定使用多应用还是多模块呢? 对于 ...

  8. MicroPython教程之TPYBoard开发板DIY小型家庭气象站

    众所周知,iPhone6/6Plus内置气压传感器,不过大家对于气压传感器还是很陌生.跟字面的意思一样,气压传感器就是用来测量气压的,但测量气压对于普通的手机用户来说又有什么作用呢? 海拔高度测量 对 ...

  9. [Spark SQL] SparkSession、DataFrame 和 DataSet 练习

    本課主題 DataSet 实战 DataSet 实战 SparkSession 是 SparkSQL 的入口,然后可以基于 sparkSession 来获取或者是读取源数据来生存 DataFrameR ...

  10. ArcGis连接oracle失败:ORA-6413:连接未打开

    问题: 通过ARCMap 添加Oracle数据库连接时提示,ORA-6413:连接未打开. 运行环境: ArcGis 10.2 Oracle 10g 解决方法: 通过上网查找解决方法,网友说" ...