[国家集训队][bzoj 2152] 聪聪可可 [点分治]
题面:
http://www.lydsy.com/JudgeOnline/problem.php?id=2152
思路:
题目要求统计书上路径信息,想到树上分治算法
实际上这是一道点分治裸题,我就不瞎BB思路了,直接上做法。
对于一个节点,设dis[i]为其他节点到这个节点的距离 MOD 3
那么可以证明,一条经过该节点的合法路径(i,j),( dis[i] + dis[j] ) % 3==0
因此对每个节点求出其子树内的dis,经过该点的路径数即为(dis[i]==1的点数)*(dis[i]==2的点数)*2 + (dis[i]==0的点数)^2
递归求解
递归进入一个节点u时,ans先加入calc(u,0),即为上述求解过程(dis[u]==0开始)。
每一次对于当前递归到的节点的每一棵子树,ans先减去dis(v,e[i].w),即为从(dis[v]==e[i].w)开始,为的是去掉重复计算的部分。
求这个子树的重心
方法:
递归进入子树中每一个节点,统计其子最大的子树大小(包括连向其父节点的那一棵)
这个最大值最小的节点就是树的重心。
如果每次从这里进入,那么进入的子树的size一定小于整棵当前树的size的一半
这样递归下去最多log n层
求完这棵子树的重心以后从这个重心递归进入,求该子树的解
最后ans即为答案数目(ans初始为0)
Code:
// luogu-judger-enable-o2
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
void _swap(int &x,int &y){x^=y;y^=x;x^=y;}
int _max(int x,int y){return (x>y)?x:y;}
inline int read(){
int re=,flag=;char ch=getchar();
while(ch>''||ch<''){
if(ch=='-') flag=-;
ch=getchar();
}
while(ch>=''&&ch<='') re=(re<<)+(re<<)+ch-'',ch=getchar();
return re*flag;
}
int n,cnt,ans,dis[],first[],tmp[],root,siz[],son[],sum;
bool vis[];
struct edge{
int to,next,w;
}a[];
inline void add(int u,int v,int w){
a[++cnt]=(edge){v,first[u],w};first[u]=cnt;
a[++cnt]=(edge){u,first[v],w};first[v]=cnt;
}
int gcd(int x,int y){return (y?gcd(y,x%y):x);};
void getroot(int u,int f){
//cout<<"getroot "<<u<<" "<<f<<"\n";
int i,v;
siz[u]=;son[u]=;
for(i=first[u];~i;i=a[i].next){
v=a[i].to;
if(v==f||vis[v]) continue;
getroot(v,u);
siz[u]+=siz[v];
son[u]=_max(son[u],siz[v]);
}
son[u]=_max(son[u],sum-siz[u]);//统计父亲节点的那棵子树,sum为当前的整棵子树的size
//cout<<"finish getroot "<<son[u]<<'\n';
if(son[u]<son[root]) root=u;
}
void gettmp(int u,int f){
//cout<<"gettmp "<<u<<" "<<f<<"\n";
int i,v;
tmp[dis[u]]++;
for(i=first[u];~i;i=a[i].next){
v=a[i].to;
if(v==f||vis[v]) continue;
//cout<<" to "<<v<<'\n';
dis[v]=(dis[u]+a[i].w)%;
gettmp(v,u);
}
}
int calc(int u,int d){//即为文中描述的calc
dis[u]=d%;tmp[]=tmp[]=tmp[]=;
gettmp(u,);
return tmp[]*tmp[]*+tmp[]*tmp[];
}
void dfs(int u){
//cout<<"dfs "<<u<<"\n";
int i,v;
vis[u]=;ans+=calc(u,);
for(i=first[u];~i;i=a[i].next){
v=a[i].to;
if(vis[v]) continue;
ans-=calc(v,a[i].w);
sum=siz[v];root=;//更新root和sum
getroot(v,u);
dfs(root);
}
}
int main(){
// freopen("cckk.in","r",stdin);
// freopen("cckk.out","w",stdout);
memset(first,-,sizeof(first));
int i,t1,t2,t3;
n=read();
for(i=;i<n;i++){
t1=read();t2=read();t3=read();
add(t1,t2,t3);
}
//cout<<"finish read in\n";
sum=n;son[]=n;//将son[0]初始化为极大值
getroot(,);
dfs();
int div=gcd(n*n,ans);//注意约分
printf("%d/%d",ans/div,n*n/div);
}
[国家集训队][bzoj 2152] 聪聪可可 [点分治]的更多相关文章
- 洛谷 P2634 BZOJ 2152 【模板】点分治(聪聪可可)
题目描述 聪聪和可可是兄弟俩,他们俩经常为了一些琐事打起来,例如家中只剩下最后一根冰棍而两人都想吃.两个人都想玩儿电脑(可是他们家只有一台电脑)……遇到这种问题,一般情况下石头剪刀布就好了,可是他们已 ...
- 【BZOJ 2152】 聪聪可可
[题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=2152 [算法] 点分治 [代码] #include<bits/stdc++.h ...
- [bzoj2152][聪聪和可可] (点分治+概率)
Description 聪聪和可可是兄弟俩,他们俩经常为了一些琐事打起来,例如家中只剩下最后一根冰棍而两人都想吃.两个人都想玩儿电脑(可是他们家只有一台电脑)……遇到这种问题,一般情况下石头剪刀布就好 ...
- 【BZOJ 2152】聪聪可可 点分治
对于一棵树,fdrt找到重心,然后分治每个子树. 在一棵以重心为根的树上,符合条件的链是: 1.过重心(根) 2.不过重心 对于1我们只需dfs出距离重心(根)的距离然后统计再减去有重叠的边 对于2我 ...
- 「BZOJ 2152」聪聪可可
题目链接 戳这 \(Solution\) 这道题看起来就像点分治对吧.没错就是点分治. 什么是点分治 如果你不会点分治,可以去看看这儿 现在看到这里,首先确保你已经会了点分治,如果不会你还往下看,听不 ...
- BZOJ 2152:聪聪可可(树上点分治)
题目链接 题意 中文题意. 思路 和上一题类似,只不过cal()函数需要发生变化. 题目中要求是3的倍数,那么可以想到 (a + b) % 3 == 0 和 (a % 3 + b % 3) % 3 = ...
- BZOJ 2117: [2010国家集训队]Crash的旅游计划 动态点分治+二分
感觉现在写点分治可快了~ 二分答案,就可以将求第 $k$ 大转换成一个判断问题,直接拿点分树判断一下就行了. #include <cstdio> #include <vector&g ...
- bzoj 2152聪聪可可
2152: 聪聪可可 Time Limit: 3 Sec Memory Limit: 259 MB Description 聪聪和可可是兄弟俩,他们俩经常为了一些琐事打起来,例如家中只剩下最后一根冰 ...
- bzoj2152 / P2634 [国家集训队]聪聪可可(点分治)
P2634 [国家集训队]聪聪可可 淀粉质点分治板子 边权直接 mod 3 直接点分治统计出所有的符合条件的点对再和总方案数约分 至于约分.....gcd搞搞就好辣 #include<iostr ...
随机推荐
- 123apps-免费网络应用
前言 在Jianrry`s博客看见推荐这个网址,试用了一下感觉还不错.主要是完全免费!!就当备用吧 网站介绍 123apps 网站地址:https://123apps.com/cn/ 旗下网站: PD ...
- react树状组件
最近在react项目中需要一个树状组件,但是又不想因为这个去引入一套UI组件,故自己封装了一个基于react的树状组件, 个人认为比较难得部分在于数据的处理,话不多说直接上代码: 下面是tree.js ...
- java: 非法字符: \65279
IDEA导入项目后,编译的时候出现Error:(1, 1) java: 非法字符: \65279: 修改:找到编译报错的文件,用Notepad++工具,以UTF-8无BOM格式编码保存,然后重新编译即 ...
- Solr7部署报错:java.lang.NoSuchMethodError: javax.servlet.ServletInputStream.isFinished()Z
错误信息: Servlet.service() for servlet [default] in context with path [/solr] threw exception [Filter e ...
- 数据库引擎InnoDB和myisam的区别和联系
1.ENGINE=InnoDB 数据库存储引擎,DEFAULT 默认,CHARSET=utf8 数据库字符编码 2.数据库的存储引擎, mysql中engine=innodb和engine=myisa ...
- Django之视图和URL配置
1.在创建项目时,Django会自动创建URL配置,在urls.py文件中 文件的默认内容如下所示: """mysite URL Configuration The ur ...
- Python 正则表达式 贪心匹配和非贪心匹配
Python的正则表达式默认是“贪心匹配”,即在有第二义的情况下,尽可能匹配最长的字符串,在正则表达式的花括号后面跟上问号,可以变为非贪心模式 >>> >>> ha ...
- PHP array_multisort()函数超详细理解
项目中用到这个函数了 ,起初对这个函数一直是懵逼状态,文档都看的朦朦胧胧的 网上无意间看到这篇文章 ,写的超级详细,收藏了 . 当然要先放原地址:https://www.cnblogs.com/WuN ...
- Linux 面试的一些基础命令
1.查询服务器负载 (1)uptime [root@oldboy ~]# uptime 20:17:18 up 7:41, 2 users, load average: 0.00, 0.00, 0.0 ...
- as API一些容易忘记的属性和方法
1.在flash动画里的一些动态文本会随着动画的执行,有抖动,解决问题的方法: tt为动画里的动态文本,tt.transform.matrix=null;