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

题意:

有一棵树,求满足x到y距离小于等于m的无序点对(x,y)的个数。

思路:

第一次写树上的乱搞系列。。。

对于此题,树上的分治。愚见如下。

假设有如图:

以root为根,点对(x,y)有四种情况。

  • 先说第四种,第四种是D-B-A-root-I..-X(经过root),dis(D,X)>m,无效,此处不考虑了。
  • 第一种:A-root-I,经过root,而且dis(A,I)<=m,有效,累加。

  • 第二种:B-A-C,不经过root,但是dis(B,root)+dis(root,C)<=m,有效,累加。但是在当A为根时,点对(B,C)距离满足要求,肯定还会被算一次,所以此时需要减去儿子为根的某些部分。
  • 第三种:D-B-A-C,不经过root,而且dis(D,root)+dis(root,C)>m,所以此处不累加。但是dis(B,A)+dis(A,C)<=m,当root下降到某点时会累加,这也是第二种需要减去的原因,防止累加两次。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 20010
using namespace std;
int m,head[N],to[N],len[N],next[N],cnt,sz[N];
int deep[N],root,vis[N],son[N],sn,d[N],tot,ans;
//son[]最大儿子树,sz[]子树。
//vis[]表示是否做为根使用过。
void add(int x,int y,int z)
{
to[++cnt]=y,len[cnt]=z,next[cnt]=head[x],head[x]=cnt;
}
void getroot(int u,int fa)
{
son[u]=,sz[u]=;
for(int i=head[u];i;i=next[i])
if(to[i]!=fa&&!vis[to[i]]){
getroot(to[i],u);sz[u]+=sz[to[i]];
son[u]=max(son[u],sz[to[i]]);
}
son[u]=max(son[u],sn-sz[u]);
if(son[root]>son[u]) root=u;
}
void getdeep(int x,int fa)
{
d[++tot]=deep[x];
for(in
t i=head[x];i;i=next[i])
if(to[i]!=fa&&!vis[to[i]])
deep[to[i]]=deep[x]+len[i],getdeep(to[i],x);
}
int calc(int x)
{
tot=,getdeep(x,),sort(d+,d+tot+);
int i=,j=tot,sum=;
while(i<j) { //保证了不重复
if(d[i]+d[j]<=m) sum+=j-i,i++ ; //d[]+d[]<m的个数。利用了双指针的思想
else j--;
}
return sum;
}
void dfs(int u)
{
deep[u]=;vis[u]=;ans+=calc(u);
for(int i=head[u];i;i=next[i])
if(!vis[to[i]]){
deep[to[i]]=len[i];ans-=calc(to[i]);//居然是抽屉原理。。。 细思极恐
sn=sz[to[i]];root=;getroot(to[i],);dfs(root);
}
}
int main()
{
int n,i,x,y,z;
while(~scanf("%d%d",&n,&m)&&(n||m)){
memset(head,,sizeof(head));
memset(vis,,sizeof(vis));
cnt=; ans=;
for(i=;i<n;i++){
scanf("%d%d%d",&x,&y,&z)
add(x,y,z);add(y,x,z);
}
root=; son[]=0x7fffffff; sn=n;
getroot(,); dfs(root);
printf("%d\n",ans);
}
return ;
}

POJ1741 Tree(树的点分治基础题)的更多相关文章

  1. POJ1741——Tree(树的点分治)

    1 /* *********************************************** 2 Author :kuangbin 3 Created Time :2013-11-17 1 ...

  2. 【poj1741】Tree 树的点分治

    题目描述 Give a tree with n vertices,each edge has a length(positive integer less than 1001). Define dis ...

  3. hdu 4812 D Tree(树的点分治)

    D Tree Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 102400/102400 K (Java/Others) Total ...

  4. POJ 1741 Tree(树的点分治,入门题)

    Tree Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 21357   Accepted: 7006 Description ...

  5. [poj1741][tree] (树/点分治)

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

  6. POJ1741 Tree 树分治模板

    http://poj.org/problem?id=1741   题意:一棵n个点的树,每条边有距离v,求该树中距离小于等于k的点的对数.   dis[y]表示点y到根x的距离,v代表根到子树根的距离 ...

  7. 【POJ 1741】 Tree (树的点分治)

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

  8. poj1741_Tree(树的点分治入门题)

    题目链接:poj1741_Tree 题意: 给你一颗n个节点的树,每条边有一个值,问有多少点对(u,v),满足u->v的最短路径小于k. 题解: 典型的树的分治,板子题. #include< ...

  9. POJ1741(SummerTrainingDay08-G 树的点分治)

    Tree Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 23380   Accepted: 7748 Description ...

随机推荐

  1. HTTP/HLS/RTMP超级负载测试工具(转)

    这个负载测试工具是网游分享的工具,可以在http://blog.csdn.net/win_lin/article/details/11835011 或者https://github.com/winli ...

  2. Jmeter 05 JMeter元件详解

    1. JMeter 逻辑控制器 Switch条件控制器.While条件控制器.交替控制器.仅一次控制器.随机控制器.随机顺序控制器.条件控制器(如果(if)).循环控制器.录制控制器.ForEach控 ...

  3. 【BZOJ4069】[Apio2015]巴厘岛的雕塑 按位贪心+DP

    [BZOJ4069][Apio2015]巴厘岛的雕塑 Description 印尼巴厘岛的公路上有许多的雕塑,我们来关注它的一条主干道. 在这条主干道上一共有 N 座雕塑,为方便起见,我们把这些雕塑从 ...

  4. git reset和git revert

    1 git reset commit-id 直接回到某次提交,该次commit-id之后的提交都会被删除. --hard,将index和本地都恢复到指定的commit版本. 2 git revert ...

  5. [Oracle]根据字段值全库搜索相关数据表和字段

    这个需求比较冷门,但对于在某些特定的情况下,还是会有这样的需要的.好在Oracle实现还比较方便,用存储过程则轻松实现. 查询字符串: create or replace procedure sear ...

  6. [转]How Hash Algorithms Work

    来看看SHA-1到底是如何工作的 http://www.metamorphosite.com/one-way-hash-encryption-sha1-data-software

  7. redis持久化RDB详细操作步骤

    1.xshell远程登录服务器ssh root@192.168.142.130 2.切换到redis目录 3.创建一个配置文件s2-redis.conf 4.编辑文件 vi s2-redis.conf ...

  8. python+NLTK 自然语言学习处理四:获取文本语料和词汇资源

    在前面我们通过from nltk.book import *的方式获取了一些预定义的文本.本章将讨论各种文本语料库 1 古腾堡语料库 古腾堡是一个大型的电子图书在线网站,网址是http://www.g ...

  9. k近邻算法(k-nearest neighbor,k-NN)

    kNN是一种基本分类与回归方法.k-NN的输入为实例的特征向量,对应于特征空间中的点:输出为实例的类别,可以取多类.k近邻实际上利用训练数据集对特征向量空间进行划分,并作为其分类的"模型&q ...

  10. VOFM 例程

    SAP ERP 实施中,经常会用到例程开发(TCODE:VOFM).这个开发目前我用到的是影响SD和MM的定价过程.创建例程需要ACCESS KEY,这个可以通过申请得到,创建后例程会被包含在一个RE ...