Description

Give a tree with n vertices,each edge has a length(positive integer less than 1001).
Define dist(u,v)=The min distance between node u and v.

Give an integer k,for every pair (u,v) of vertices is called valid if and only if dist(u,v) not exceed k.

Write a program that will count how many pairs which are valid for a given tree.

Input

The input contains several test cases. The first line of each test case contains two integers n, k. (n<=10000) The following n-1 lines each contains three integers u,v,l, which means there is an edge between node u and v of length l.

The last test case is followed by two zeros.

Output

For each test case output the answer on a single line.

Sample Input

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

Sample Output

8
题解
求树上总共有多少点对(u,v)距离<=k
题意
初学点分治
树的重心定义:找到一个点,其所有的子树中最大的子树节点数最少,那么这个点就是这棵树的重心,删去重心后,生成的多棵树尽可能平衡
点分治就是把树按子树重心不断DFS,然后处理每个子树对答案的贡献,会用到容斥,把n^2的复杂度优化为nlogn
处理每个子树对答案的贡献,先求出重心到各个点的距离,然后sort一下,然后可以二分出满足<=k的答案
代码
 #include<stdio.h>
#include<string.h>
#include<vector>
#include<algorithm>
using namespace std; const int maxn=1e4+; vector< pair<int,int> >G[maxn];
int mx[maxn],size[maxn],vis[maxn],dis[maxn],ans,MIN,n,k,num,root;
void dfssize(int u,int fa)
{
size[u]=;
mx[u]=;
for(int i=;i<G[u].size();i++)
{
int v=G[u][i].first;
if(!vis[v]&&v!=fa)
{
dfssize(v,u);
size[u]+=size[v];
mx[u]=max(mx[u],size[v]);
}
}
}
void dfsroot(int r,int u,int fa)//r为子树的根
{
if(size[r]-size[u]>mx[u])//子树的其余节点
mx[u]=size[r]-size[u];
if(mx[u]<MIN)//root为重心
MIN=mx[u],root=u;
for(int i=;i<G[u].size();i++)
{
int v=G[u][i].first;
if(!vis[v]&&v!=fa)
dfsroot(r,v,u);
}
}
void dfsdis(int u,int fa,int d)
{
dis[num++]=d;
for(int i=;i<G[u].size();i++)
{
int v=G[u][i].first;
int w=G[u][i].second;
if(!vis[v]&&v!=fa)
dfsdis(v,u,d+w);
}
}
int cal(int r,int w)
{
int ret=;
num=;
dfsdis(r,r,w);
sort(dis,dis+num);
int L=,R=num-;
while(L<R)
{
while(dis[L]+dis[R]>k&&L<R)R--;
ret+=R-L;
L++;
}
return ret;
}
void dfs(int u)
{
MIN=n;
dfssize(u,u);
dfsroot(u,u,u);
int Grivate=root;
ans+=cal(Grivate,);
vis[root]=;
for(int i=;i<G[Grivate].size();i++)
{
int v=G[Grivate][i].first;
int w=G[Grivate][i].second;
if(!vis[v])
{
ans-=cal(v,w);
dfs(v);
}
}
}
int main()
{
while(scanf("%d%d",&n,&k)!=EOF,n||k)
{
ans=;
for(int i=;i<=n;i++)
{
G[i].clear();
vis[i]=;
}
for(int i=,u,v,w;i<n;i++)
{
scanf("%d%d%d",&u,&v,&w);
G[u].push_back({v,w});
G[v].push_back({u,w});
}
dfs();
printf("%d\n",ans);
}
return ;
}

POJ 1741 Tree(点分治点对<=k)的更多相关文章

  1. POJ 1741 Tree 求树上路径小于k的点对个数)

                                                                                                 POJ 174 ...

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

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

  3. POJ 1741 Tree 树分治

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

  4. [bzoj 1468][poj 1741]Tree [点分治]

    Description Give a tree with n vertices,each edge has a length(positive integer less than 1001). Def ...

  5. POJ 1741 Tree ——点分治

    [题目分析] 这貌似是做过第三道以Tree命名的题目了. 听说树分治的代码都很长,一直吓得不敢写,有生之年终于切掉这题. 点分治模板题目.自己YY了好久才写出来. 然后1A了,开心o(* ̄▽ ̄*)ブ ...

  6. [poj 1741]Tree 点分治

    题意 求树上距离不超过k的点对数,边权<=1000 题解     点分治.     点分治的思想就是取一个树的重心,这种路径只有两种情况,就是经过和不经过这个重心,如果不经过重心就把树剖开递归处 ...

  7. POJ - 1741 - Tree - 点分治 模板

    POJ-1741 题意: 对于带权的一棵树,求树中距离不超过k的点的对数. 思路: 点分治的裸题. 将这棵树分成很多小的树,分治求解. #include <algorithm> #incl ...

  8. POJ 1741.Tree and 洛谷 P4178 Tree-树分治(点分治,容斥版) +二分 模板题-区间点对最短距离<=K的点对数量

    POJ 1741. Tree Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 34141   Accepted: 11420 ...

  9. poj 1741 Tree(树的点分治)

    poj 1741 Tree(树的点分治) 给出一个n个结点的树和一个整数k,问有多少个距离不超过k的点对. 首先对于一个树中的点对,要么经过根结点,要么不经过.所以我们可以把经过根节点的符合点对统计出 ...

随机推荐

  1. Android引入动态库so的方法

    Android引入动态库so的方法 标签(空格分隔): Android so 第三方库 为了执行效率,会将一些CPU密集性任务如音视频解码.图像处理等放入到so中,还有也会将程序关键核心部分放入到so ...

  2. python 【winerror2】系统找不到指定的路径

    # _*_ coding:utf-8_*_from selenium import webdriver driver = webdriver.Firefox()driver.get("htt ...

  3. 简单的shell脚本练习(一)

    1:求1000一内的偶数和 方法一: #!/bin/bash #用累加实现1000以内的偶数和 sum= ;i<=;i=i+)) do sum=$(($sum+$i)); done echo $ ...

  4. php执行系统命令的四个函数shell_exec, exec, passthru, system分别的使用场景

    shell_exec() 通过 shell 环境执行命令,并且将完整的输出以字符串的方式返回.也就是说, PHP先运行一个shell环境, 然后让shell进程运行你的命令, 并且把所有输出已字符串形 ...

  5. [转]jvm调优-命令大全(jps jstat jmap jhat jstack jinfo)

    运用jvm自带的命令可以方便的在生产监控和打印堆栈的日志信息帮忙我们来定位问题!虽然jvm调优成熟的工具已经有很多:jconsole.大名鼎鼎的VisualVM,IBM的Memory Analyzer ...

  6. Kubernetes Kubelet安全认证连接Apiserver

    Kubelet使用安全认证连接Apiserver,可以用Token或证书连接.配置步骤如下. 1,生成Token命令 head -c /dev/urandom | od -An -t x | tr - ...

  7. python数据格式化之pprint

    python数据格式化之pprint 2017年06月17日 13:56:33 阅读数:2291 简介 pprint模块 提供了打印出任何Python数据结构类和方法. 模块方法: 1.class p ...

  8. HTML/CSS基础知识(一)

    Q:浏览器页面有哪三层构成,分别是什么,作用是什么? A:由三部分构成: 网页结构层(Structural Layer)——由(X)HTML等标记语言负责创建,实现页面结构. 网页表示层(Presen ...

  9. css3属性box-sizing:border-box 用法解析

    响应式Web设计经常需要我们通过百分比设置组件宽度.如果我们不考虑边框,那么很容易就可以实现,但如果你给每一列以及总宽度都采用百分比设置,那这个时候固定的边框大小就会出来捣乱.下面我们将看到一组方法去 ...

  10. Servlet-知识点

    2018年10月05日 16:52:56 yigg 阅读数:38   1.JavaWeb开发的目录结构 https://blog.csdn.net/u012661010/article/details ...