【问题描写叙述】

聪聪和可但是兄弟俩。他们俩常常为了一些琐事打起来,比如家中仅仅剩下最后一根冰棍而两人都想吃、两个人都想玩儿电脑(但是他们家仅仅有一台电脑)……遇到这样的问题,普通情况下石头剪刀布就好了,但是他们已经玩儿腻了这样的低智商的游戏。他们的爸爸快被他们的争吵烦死了,所以他发明了一个新游戏:

由爸爸在纸上画n个“点”。并用n-1条“边”把这n个“点”恰好连通(事实上这就是一棵树)。

而且每条“边”上都有一个数。接下来由聪聪和可可分别随即选一个点(当然他们选点时是看不到这棵树的),假设两个点之间全部边上数的和加起来恰好是3的倍数,则判聪聪赢,否则可可赢。

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

【输入格式】

输入的第1行包括1个正整数n。

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

【输出格式】

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

【例子输入】

5

1 2 1

1 3 2

1 4 1

2 5 3

【例子输出】

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)。
数据规模和约定
对于30%的数据,n<=1000  另有20%的数据,给出的树中每一个节点的度不超过2;

对于100%的数据。n<=20000

题解:点分治的裸题,处理重心信息的时候仅仅要处理出经过重心且模三等于0,1,2的路径条数就好了。。

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int temp,x,y,z,n,cnt,f[100001],son[100001],ans,root,sum,point[1000001],next[1000001],d[100001],num[10000001];
struct use{int st,en,val;}b[10000001];
bool isfocus[100001];
void add(int x,int y,int z){
z%=3;
next[++cnt]=point[x];point[x]=cnt;
b[cnt].st=x;b[cnt].en=y;b[cnt].val=z;
}
void findfocus(int x,int fa)
{
son[x]=1;f[x]=0;
for (int i=point[x];i;i=next[i])
if (!isfocus[b[i].en]&&b[i].en!=fa)
{
findfocus(b[i].en,x);
son[x]+=son[b[i].en];
f[x]=max(f[x],son[b[i].en]);
}
f[x]=max(f[x],sum-son[x]);
if (f[x]<f[root]) root=x;
}
void getdeep(int x,int fa)
{
num[d[x]]++;
for (int i=point[x];i;i=next[i])
if(!isfocus[b[i].en]&&b[i].en!=fa)
{
d[b[i].en]=(d[x]+b[i].val)%3;
getdeep(b[i].en,x);
}
}
int cal(int x,int now)
{
num[0]=num[1]=num[2]=0;
d[x]=now;
getdeep(x,0);
return 2*num[1]*num[2]+num[0]*num[0];
}
void work(int x)
{
ans+=cal(x,0);
isfocus[x]=true;
for (int i=point[x];i;i=next[i])
if (!isfocus[b[i].en])
{
ans-=cal(b[i].en,b[i].val);
sum=son[b[i].en];root=0;
findfocus(b[i].en,0);
work(root);
}
}
int gcd(int a,int b){return b==0? a:gcd(b,a%b);}
int main()
{
freopen("cckk.in","r",stdin);
freopen("cckk.out","w",stdout);
scanf("%d",&n);
memset(isfocus,false,sizeof(isfocus));
for (int i=1;i<=n-1;i++)
{
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);add(y,x,z);
}
f[0]=sum=n;
findfocus(1,0);
work(root);
temp=gcd(ans,n*n);
cout<<ans/temp<<"/"<<n*n/temp<<endl;
}


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

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

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

  2. 【BZOJ2152】聪聪可可(点分治)

    [BZOJ2152]聪聪可可(点分治) 题面 Description 聪聪和可可是兄弟俩,他们俩经常为了一些琐事打起来,例如家中只剩下最后一根冰棍而两人都想吃.两个人都想玩儿电脑(可是他们家只有一台电 ...

  3. BZOJ2152 [国家集训队] 聪聪可可 [点分治]

    题目传送门 聪聪可可 Time Limit: 3 Sec  Memory Limit: 259 MBSubmit: 5237  Solved: 2750[Submit][Status][Discuss ...

  4. BZOJ2152 聪聪可可 【点分治】

    BZOJ2152 聪聪可可 Description 聪聪和可可是兄弟俩,他们俩经常为了一些琐事打起来,例如家中只剩下最后一根冰棍而两人都想吃.两个人都想玩儿电脑(可是他们家只有一台电脑)--遇到这种问 ...

  5. BZOJ2152 聪聪可可 (点分治)

    2152: 聪聪可可 题意: 在一棵边带权的树中,问任取两个点,这两个点间的权值和是3的倍数的概率. 思路: 经典的点分治题目. 利用点分治在计算所有路径长度,把路径长度对3取模,用t[0],t[1] ...

  6. BZOJ2152[国家集训队]聪聪可可——点分治

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

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

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

  8. 【bzoj2152】聪聪可可 树的点分治

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

  9. [BZOJ2152]聪聪可可 点分治/树形dp

    2152: 聪聪可可 Time Limit: 3 Sec  Memory Limit: 259 MB Submit: 3602  Solved: 1858 [Submit][Status][Discu ...

随机推荐

  1. Spoj8093 Sevenk Love Oimaster

    题目描述 题解: 对于所有n串建广义后缀自动机. (广义后缀自动机唯一区别就是每次将las附成1,并不需要在插入时特判) 建完后再建出parent树,然后用dfs序+树状数组搞区间不同种类. 其实就是 ...

  2. java(List或Array数组)求交集、并集、差集, 泛型工具类

    业务需要求不同类型的交集.并集.差集为避免代码冗余编写工具类. 注:list 转数组需传入数组,如果将原数组传入将会改变原数组的值,同时泛型数组又不可以实例化,解决方案:Arrays.copyOf(n ...

  3. KNN算法原理及实现

    1.KNN算法概述 kNN算法的核心思想是如果一个样本在特征空间中的k个最相邻的样本中的大多数属于某一个类别,则该样本也属于这个类别,并具有这个类别上样本的特性.该方法在确定分类决策上只依据最邻近的一 ...

  4. 爬虫app信息抓取之apk反编译抓取

    之前也抓过一些app,数据都比较好取,也没有研究的太深,毕竟还有android 模拟器+ appium 的方法.直到遇见了一款app ,具体名字就不说了,它安装在模拟器上竟然打不开 !!第一次遇见上网 ...

  5. c和c++如何把一个整数转化为string

    c和c++如何把一个整数转化为string C++: 一.string转int的方式 采用最原始的string, 然后按照十进制的特点进行算术运算得到int,但是这种方式太麻烦,这里不介绍了. 采用标 ...

  6. ArrayList练习之存储字符串并遍历

    在myArrayList项目下 新建一个包 在这个包中新建一个类:ArrayListDemo4.java ArrayListDemo4.java import java.util.ArrayList; ...

  7. 安装mysql后无法找到临时密码的解决方案

    安装mysql后无法找到临时密码的解决方案 一.环境 系统:CentOS7mysql:5.7.20 二.解决步骤 step1:修改/etc/my.cnf添加: skip-grant-tables   ...

  8. [Go]通道(channel)的基本操作

    通道类型是Go语言自带的.唯一一个可以满足并发安全性的类型,在声明并初始化一个通道时,需要用到内建函数make,传给make函数的第一个参数应该代表通道的具体类型的类型字面量. 如类型字面量 chan ...

  9. POJ 1236 学校网络间的强连通

    题目大意: N个学校之间有单向的网络,每个学校得到一套软件后,可以通过单向网络向周边的学校传输.问题1:初始至少需要向多少个学校发放软件,使得网络内所有的学校最终都能得到软件.问题2:至少需要添加几条 ...

  10. HDU1711 最基础的kmp算法

    Problem Description Given two sequences of numbers : a[1], a[2], ...... , a[N], and b[1], b[2], .... ...