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代码:

 #include <bits/stdc++.h>
using namespace std;
inline int read()//读入优化
{
int x=,f=;//f表示符号,x表示首位数字0
char ch=getchar();
while(ch<''||ch>'')//如果ch不是数字
{
if(ch=='-')//如果是符号就改变符号
f=-;
ch=getchar();
}
while(ch>=''&&ch<='')//如果ch是数字,接下来的每位数字
{
x=x*+ch-'';//将数字添加进x内
ch=getchar();
}
return x*f;//返回数值
}
inline void write(int x)//输出优化
{
if(x<)//判断小于0的情况
{
putchar('-');
x=-x;
}
if(x>)//保存每一位
{
write(x/);
}
putchar(x%+'');//输出
}
inline int gcd(int a,int b)//求最大公因数
{
return b==?a:gcd(b,a%b);
}
const int N=;
int last[N];
int son[N];//son表示树的大小
int f[N];//表示最大子树的节点数
int d[N];//表示到k的距离
int t[N];//表示到k的距离%3=0的点的个数
bool vis[N];
struct Edge//前向星存边
{
int to,next,v;
}edge[N<<];//保存双向图
int n,cnt,ans,root,sum;
inline void addage(int u,int v,int w)//连双向边
{
edge[++cnt].to=v;
edge[cnt].next=last[u];
last[u]=cnt;
edge[cnt].v=w;
edge[++cnt].to=u;
edge[cnt].next=last[v];
last[v]=cnt;
edge[cnt].v=w;
}
inline void getroot(int x,int fa)//寻找根节点,根节点满足最大儿子子树规模最小,求重心的操作
{
son[x]=;//son[x]表示x的树大小
f[x]=;//f[x]表示x最大子树的节点数
for(int i=last[x];i;i=edge[i].next)//枚举和x相邻的每一个点
{
if(!vis[edge[i].to]&&edge[i].to!=fa)//如果没有被删除,并且当前节点不是根节点
{
getroot(edge[i].to,x);
son[x]+=son[edge[i].to];//子树规模
f[x]=max(f[x],son[edge[i].to]);
}
}
f[x]=max(f[x],sum-son[x]);//x最大子树的节点数f[x]=max(f[x],与此子树大小-f[x])
if(f[x]<f[root])
root=x;
}
inline void getdeep(int x,int fa)//获得每个点到cal中的x的距离,即root
{
t[d[x]]++;//统计到k距离的个数,//将对应余数的数目+1
for(int i=last[x];i;i=edge[i].next)//枚举和x相邻的每一个点
{
if(!vis[edge[i].to]&&edge[i].to!=fa)//如果没有被删除,并且当前节点不是根节点
{
d[edge[i].to]=(d[x]+edge[i].v)%;
getdeep(edge[i].to,x);
}
}
}
inline int cal(int x,int now)//t[0]表示到k的距离%3=0的点的个数,t[1]表示余数为1,t[2]表示余数为2,所以计算方案数时,t[0]内部解决,t[1]和t[2]两两搭配
{
t[]=t[]=t[]=;//余数清0
d[x]=now;
getdeep(x,);//getdeep更新子树的root的值,计算深度root
return t[]*t[]*+t[]*t[];//计算路径数
}
inline void work(int x)//表示work以x为根的子树,此时x已经是重心
{
ans+=cal(x,);//统计不同子树通过重心的个数
vis[x]=;//把x从树中删除
for(int i=last[x];i;i=edge[i].next)//枚举和x相邻的每一个点
{
if(!vis[edge[i].to])//如果没有被删除,说明在某一棵子树中
{
ans-=cal(edge[i].to,edge[i].v);//去除在同一个子树中被重复统计的
root=;
sum=son[edge[i].to];
getroot(edge[i].to,);//找到所在子树的重心root,更新重心root
work(root);//递归处理root,求解子树
}
}
}
int main()
{
n=read();
for(int i=;i<n;i++)//建图
{
int u=read();
int v=read();
int w=read()%;
addage(u,v,w);//建立一个无向图
}
f[]=n;
sum=n;
getroot(,);
work(root);
int t=gcd(ans,n*n);
printf("%d/%d\n",ans/t,n*n/t);
return ;
}

洛谷 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. CentOS5 可用yum源

    [base] name=CentOS-$releasever - Base #mirrorlist=http://mirrorlist.centos.org/?release=$releasever& ...

  2. 自定义tab吸顶效果一(原理)

    PS:问题:什么是吸顶,吸顶有什么作用,吸顶怎么使用? 在很多app商城中,介绍软件的时候就会使用吸顶效果, 吸顶有很多作用,一个最简单粗暴的作用就是,让用户知道此刻在浏览哪个模块,并可以选择另外的模 ...

  3. KD树

    k-d树 在计算机科学里,k-d树( k-维树的缩写)是在k维欧几里德空间组织点的数据结构.k-d树可以使用在多种应用场合,如多维键值搜索(例:范围搜寻及最邻近搜索).k-d树是空间二分树(Binar ...

  4. BCL和CoreFx的区别

    bcl是.netframework clr 的基础库corefx是.net core clr的基础库

  5. C# winForm资源文件实现多语言切换

    这是我目前看到过最简单的多语言切换了 操作步驟 介面上的多語 Step1.將表單的Localizable屬性設為True Step2.切換表單的Language屬性為欲使用的語系 設完後會在分頁標籤上 ...

  6. ES6(四)字符串的扩展

    1.字符的表示方式 最早在  \u0000-\uFFFF 之间的字符已经足够使用吗,每个字符占两个字节,超出范围,必须使用双字节形式表达, 即每个字符占四个字节.超出范围的字符,会被解读成  \uXX ...

  7. e.target和this的区别

    ```e.target与this的区别 event.target表示发生点击事件的元素this表示注册点击事件的元素 this 等于 e.currentTarget 指的是现在的目标this是所有原生 ...

  8. NPOI 2.0 教程

    NPOI2.0帮助官方地址 目录 1. 前言 1.1 NPOI 2.0与NPOI 1.x的区别 1.2 NPOI 2.0模块简介 1.3 自动识别并打开Excel 2003和Excel 2007文件 ...

  9. sql server 各种等待类型-转

    等待的类型 资源等待 当某个工作线程请求访问某个不可用的资源(因为该资源正在由其他某个工作线程使用,或者该资源尚不可用)时,便会发生资源等待.资源等待的示例包括锁等待.闩锁等待.网络等待以及磁盘 I/ ...

  10. WebDriver的等待方式

    /* * 1.线程休眠 * 2.隐式等待 * 3.显示等待 * */ package com.sfwork; import java.util.concurrent.TimeUnit; import ...