题意:一棵n个点的树,每条边有距离v,求该树中距离小于等于k的点的对数。
 
dis[y]表示点y到根x的距离,v代表根到子树根的距离;
那么不在同一棵子树中的两点i、j之间的距离为dis[i]+dis[j]; ① 
 
设得到这个距离的时间复杂度为O(w);
如果我们层层如此递归即可得到所有的点对数量,可以证明复杂度为O(logn*w);
 
因为n的范围为(n<=10000)所以我们需要w与n近似;
 
那么此时问题转化为了如何在大约为O(n)的复杂度内得到①;
一个个计算不在同一子树中显然是麻烦的,如果选择先计算整棵树的点对数量然后去掉重复计数的点对数问题就可以得到简化;
 
如果只是计算一棵树下符合条件dis[j]+dis[i]<=k的点对数量,我们将距离sort,很容易在 log(树的大小) 的复杂度下把问题解决,再用几乎同样的时间减去每一棵子树中符合dis[j]+dis[i]+2*v<=k的点对的数量就可以得到答案。
那么总时间复杂度为O(n*logn*logn);
 
当然这只是理想情况,如果这棵树退化为一条链,复杂度则会变为O(n*n*logn)显然是超时的;
所以在每次递归前O(n)的复杂度找一下树的重心,
 
代码如下
 #include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
//using namespace std;
const int maxn=;
const double eps=1e-;
const int modn=;
int n,k;
struct nod{
int y,next;
int v;
}e[maxn*];
int head[maxn]={},siz[maxn]={},ma[maxn]={},dis[maxn]={};
int tot=,tot1,root=,now,ans;
bool vis[maxn]={};
void init(int x,int y,int v){
e[++tot].y=y;
e[tot].next=head[x];
e[tot].v=v;
head[x]=tot;
}
void getsiz(int x,int fa){ //某子树的大小
int y;
siz[x]=;
ma[x]=;
for(int i=head[x];i;i=e[i].next){
y=e[i].y;
if(y!=fa&&!vis[y]){
getsiz(y,x);
siz[x]+=siz[y];
ma[x]=std::max(siz[y],ma[x]);
}
}
}
void cen(int r,int x,int fa){ //找重心
int y;
if(siz[r]-siz[x]>ma[x]){
ma[x]=siz[r]-siz[x];
}
if(ma[x]<now){
root=x;now=ma[x];
}
for(int i=head[x];i;i=e[i].next){
y=e[i].y;
if(y!=fa&&!vis[y]){
cen(r,y,x);
}
}
}
void getdis(int x,int fa,int di){ //子树中各个点到该子树根的距离
int v,y;
dis[++tot1]=di;
for(int i=head[x];i;i=e[i].next){
v=e[i].v;y=e[i].y;
if(y!=fa&&!vis[y]){
getdis(y,x,di+v);
}
}
}
int sum(int x,int d){ //点对数
tot1=;
getdis(x,,d);
std::sort(dis+,dis++tot1);
int i=,j=tot1;
int cnt=;
while(i<j){
while(dis[i]+dis[j]>k&&i<j){
j--;
}
cnt+=j-i;
i++;
}
return cnt;
}
void dfs(int x){
int y;
now=maxn;root=x;
getsiz(x,);
cen(x,x,);
ans+=sum(root,);
vis[root]=;
for(int i=head[root];i;i=e[i].next){
y=e[i].y;
if(!vis[y]){
ans-=sum(y,e[i].v);
dfs(y);
}
}
}
void yu(){
memset(head,,sizeof(head));
memset(vis,,sizeof(vis));
tot=;ans=;
}
int main(){
while((~scanf("%d%d",&n,&k))&&(n!=||k!=)){
yu();
int x,y,v;
for(int i=;i<n;i++){
scanf("%d%d%d",&x,&y,&v);
init(x,y,v);
init(y,x,v);
}
dfs();
printf("%d\n",ans);
}
return ;
}

POJ1741 Tree 树分治模板的更多相关文章

  1. poj 1744 tree 树分治

    Tree Time Limit: 1000MS   Memory Limit: 30000K       Description Give a tree with n vertices,each ed ...

  2. 【POJ1741】Tree 树分而治之 模板略?

    做广告: #include <stdio.h> int main() { puts("转载请注明出处[vmurder]谢谢"); puts("网址:blog. ...

  3. 【BZOJ-1468】Tree 树分治

    1468: Tree Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1025  Solved: 534[Submit][Status][Discuss] ...

  4. HDU 4812 D Tree 树分治+逆元处理

    D Tree Problem Description   There is a skyscraping tree standing on the playground of Nanjing Unive ...

  5. POJ 1741 Tree 树分治

    Tree     Description Give a tree with n vertices,each edge has a length(positive integer less than 1 ...

  6. POJ 1741.Tree 树分治 树形dp 树上点对

    Tree Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 24258   Accepted: 8062 Description ...

  7. HDU4871 Shortest-path tree(树分治)

    好久没做过树分治的题了,对上一次做是在南京赛里跪了一道很裸的树分治题后学的一道,多校的时候没有看这道题,哪怕看了感觉也看不出来是树分治,看出题人给了解题报告里写了树分治就做一下好了. 题意其实就是给你 ...

  8. HDU4670 Cube number on a tree 树分治

    人生的第一道树分治,要是早点学我南京赛就不用那么挫了,树分治的思路其实很简单,就是对子树找到一个重心(Centroid),实现重心分解,然后递归的解决分开后的树的子问题,关键是合并,当要合并跨过重心的 ...

  9. [POJ1741]Tree(点分治)

    树分治之点分治入门 所谓点分治,就是对于树针对点的分治处理 首先找出重心以保证时间复杂度 然后递归处理所有子树 对于这道题,对于点对(u,v)满足dis(u,v)<=k,分2种情况 路径过当前根 ...

随机推荐

  1. wepy 使用组件时一个注意事项。。。

    组件传值prop 必须使用指定引用地址的数据 如果像下面这样 取为空shop 中的phone ,后续获取数据或就算 shop中有phone元素 子组件也无法获取到修改后的值 <template& ...

  2. 用java代码调用shell脚本执行sqoop将hive表中数据导出到mysql

    1:创建shell脚本 touch sqoop_options.sh chmod 777 sqoop_options.sh 编辑文件  特地将执行map的个数设置为变量  测试 可以java代码传参数 ...

  3. 用jquery实现小火箭到页面顶部的效果

    恩,不知道之前在哪看过一个页面效果就是如果页面被滑动了就出现一个小火箭,点击这个小火箭就可以慢慢回到页面顶部,闲的没事,自己搞了一下 需要引入jquery 代码和布局都很简单 <!DOCTYPE ...

  4. Git HTTPS 方式自动保存用户名密码

    一行命令搞定: git config --global credential.helper wincred 第一次输入用户名和密码提交,第二次就不需要了 参考: https://help.github ...

  5. PHP7+Nginx的配置与安装教程详解

    下面脚本之家小编把PHP7+Nginx的配置与安装教程分享给大家,供大家参考,本文写的不好还请见谅. 系统环境:centos6.5 x64 软件版本:nginx-1.10.0 php-7.0.6 安装 ...

  6. python并发编程之进程、线程、协程的调度原理(六)

    进程.线程和协程的调度和运行原理总结. 系列文章 python并发编程之threading线程(一) python并发编程之multiprocessing进程(二) python并发编程之asynci ...

  7. js弱数据类型的坑

    1.从表单获取的value是字符串,如果需要为数字相加,则需要转换为number类型 <input type="number" id="val1"> ...

  8. 在Mac上搭建Python虚拟环境

    安装 virtualenv $ sudo pip install virtualenv 然后建立一个测试目录: $ mkdir testvirtual $ cd testvirtual 就可以成功创建 ...

  9. CentOS 7.1使用yum安装MySql5.6.24

    http://www.cnblogs.com/yuanfeiblog/p/5276492.html

  10. EL(表达式)语言的几种运算符

    1.EL的基本语法 (1)EL表达式语法:以${开头,以}结束,中间为合法的表达式,具体语法格式如下: ${expression} (2)参数说明:Expression:指定要输出的内容,可以是字符串 ...