Description

给一棵有n个节点的树,每条边都有一个长度(小于1001的正整数)。 
定义dist(u,v)=节点u到节点v的最短路距离。 
给出一个整数k,我们称顶点对(u,v)是合法的当且仅当dist(u,v)不大于k。 
写一个程序,对于给定的树,计算有多少对顶点对是合法的。

Input

输入包含多组数据。 
每组数据的第一行有两个整数N,K(N<=10000)。接下来N-1行每行有三个整数u,v,l,代表节点u和v之间有一条长度l的无向边。 
输入结束标志为N=K=0.

Output

对每组数据输出一行一个正整数,即合法顶点对的数量。

Sample Input

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

Sample Output

8

树分治裸题:

每一次找到树的重心,使得二分复杂度降为logn,然后每一个小区间做相同处理:

设 dis[i]表示到当前根节点X的距离 找到以当前节点X为根的满足dis[i]+dis[j]<=k的所有方案。

在统计的时候可能存在把同一子树满足dis[i]+dis[j]<=k的也统计进答案中,产生重复方案。

于是我们要减去每一棵子树中满足dis[i]+dis[j]<=k的方案。

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std; int n,k; int gi()
{
int str=;char ch=getchar();
while(ch>'' || ch<'')ch=getchar();
while(ch>='' && ch<='')str=str*+ch-'',ch=getchar();
return str;
} const int N=;int sum=;int ans=;
int num=,head[N];int root=;int son[N];int f[N]={};bool vis[N];int dis[N];
int b[N];
struct Lin
{
int next,to,dis;
}a[N*]; void init(int x,int y,int z)
{
a[++num].next=head[x];
a[num].to=y;
a[num].dis=z;
head[x]=num;
} void getroot(int x,int last)
{
son[x]=;f[x]=;
int u;
for(int i=head[x]; i ;i=a[i].next)
{
u=a[i].to;
if(u==last || vis[u])continue;
getroot(u,x);
son[x]+=son[u];
f[x]=max(f[x],son[u]);
}
f[x]=max(f[x],sum-son[x]);
if(f[x]<f[root])root=x;
return ;
} void getdis(int x,int last)
{
int u;
b[++b[]]=dis[x];
for(int i=head[x];i;i=a[i].next)
{
u=a[i].to;
if(u==last || vis[u])continue;
dis[u]=dis[x]+a[i].dis;
getdis(u,x);
}
return ;
} int cal(int x,int dd)
{
int tot=,u;dis[x]=dd;
b[]=;
getdis(x,);
sort(b+,b+b[]+);
int l=,r=b[];
while(l<r)
{
if(b[l]+b[r]<=k)tot+=r-l,l++;
else r--;
}
return tot;
} void work(int x)
{
ans+=cal(x,);
vis[x]=;
int u;
for(int i=head[x];i;i=a[i].next)
{
u=a[i].to;
if(vis[u])continue;
ans-=cal(u,a[i].dis);
root=;sum=son[u];
getroot(u,x);
work(root);
}
return ;
} void Clear()
{
memset(vis,,sizeof(vis));
f[]=;
memset(a,,sizeof(a));
memset(head,,sizeof(head));
memset(dis,,sizeof(dis));
num=;
}
int main()
{
while(scanf("%d%d",&n,&k))
{
if(!n && !k)return ;
int x,y,z;
Clear();
for(int i=;i<=n-;i++)
{
x=gi();y=gi();z=gi();
init(x,y,z);init(y,x,z);
}
sum=n;
ans=;
root=;
getroot(,);
work(root);
printf("%d\n",ans);
}
return ;
}

[POJ1741]树上的点对 树分治的更多相关文章

  1. 算法笔记--树的直径 && 树形dp && 虚树 && 树分治 && 树上差分 && 树链剖分

    树的直径: 利用了树的直径的一个性质:距某个点最远的叶子节点一定是树的某一条直径的端点. 先从任意一顶点a出发,bfs找到离它最远的一个叶子顶点b,然后再从b出发bfs找到离b最远的顶点c,那么b和c ...

  2. POJ1741:Tree——题解+树分治简要讲解

    http://poj.org/problem?id=1741 题目大意:给一棵树,求点对间距离<=k的个数. ———————————————————— 以这道题为例记录一下对于树分治的理解. 树 ...

  3. POJ1741 经典树分治

    题意:有一棵树,每条边有一个距离,求dis(u,v)<=k的点的对数 题解:树分治,对于一颗树上的两点,要么在同一颗子树上,要么在不同子树上,要么一个点是根,另一个在某一子树上,对于第一种情况我 ...

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

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

  5. 树分治&树链剖分相关题目讨论

    预备知识 树分治,树链剖分   poj1741 •一棵有n个节点的树,节点之间的边有长度.方方方想知道,有多少个点对距离不超过m 题解 点分治模板题.详见我早上写的http://www.cnblogs ...

  6. 树分治learning

    学习了树的点分治,树的边分治似乎因为复杂度过高而并不出众,于是没学 自己总结了一下 有些时候面对一些树上的结构 并且解决的是和路径有关的问题的时候 如果是多个询问 关注点在每次给出两个点,求一些关于这 ...

  7. UVALive 7148 LRIP【树分治+线段树】

    题意就是要求一棵树上的最长不下降序列,同时不下降序列的最小值与最大值不超过D. 做法是树分治+线段树,假设树根是x,y是其当前需要处理的子树,对于子树y,需要处理出两个数组MN,MX,MN[i]表示以 ...

  8. COJ 0970 WZJ的数据结构(负三十)树分治

    WZJ的数据结构(负三十) 难度级别:D: 运行时间限制:1000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 给你一棵N个点的无根树,点和边上均有权值.请你设计 ...

  9. Poj1741-Tree(树分治)

    题意:找树上有多少对距离小于K的对数解析:树分治模板题,见注释 代码 #include<cstdio> #include<cstring> #include<string ...

随机推荐

  1. Python split()方法

    Python split()方法 描述 Python split()通过指定分隔符对字符串进行切片,如果参数num 有指定值,则仅分隔 num 个子字符串 语法 split()方法语法: str.sp ...

  2. iOS开发-OC分支结构

     BOOL类型 返回值:真:YES  假:NO BOOL数据类型占一个字节的内存空间,占位符为%d. 计算机在识别时,YES就替换成1,NO就替换成0. bool是C语言中的布尔类型,返回值为true ...

  3. map的infowindow的show事件(ArcGIS API for JS)

  4. windows系统下安装 node.js (node.js安装及环境配置)

    node.js简介 Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境. Node.js 使用了一个事件驱动.非阻塞式 I/O 的模型,使其轻量又高效. Node. ...

  5. GitHub 上下载单个文件夹

    写代码的一定经常去github上查看.下载一些源码,有时候会想下载一个项目中的一个文件夹里的内容,但是github上只提供了整个项目的下载,而整个项目里东西太多,压缩的文件太大,github的下载速度 ...

  6. JAVA_SE基础——39.继承

    在面向对象程序设计中,可以从已有的类派生出新类. 这称做继承(inheritance). 白话解释: 例子1:继承一般是指晚辈从父辈那里继承财产,也可以说是子女拥有父母给予他们的东西. 例子2:猫和狗 ...

  7. Ubuntu server 16.04 中文版 终端不能显示中文的解决办法探讨

    对于刚安装成功的Ubuntu server 16.04中文版,在终端显示中文的地方总是出现菱形的图标,看来该版本内置终端暂时不支持中文显示, 还是本人不知道具体操作配置,现通过百度查找以下几个解决方案 ...

  8. selenium多个标签页的切换(弹出新页面的切换)

    1_windows = driver.current_window_handle #定位当前页面句柄 all_handles = driver.window_handles #获取全部页面句柄 for ...

  9. 微信小程序如何动态增删class类名

    简述 由于微信小程序开发不同于以往的普通web开发, 因此无法通过js获取wxml文件的dom结构, 因此从js上直接添加一个类名应该不可能了. 可是我们可以通过微信小程序数据绑定以及view标签的& ...

  10. 您的 Java 代码安全吗 — 还是暴露在外? 【转】

    在开发 Java Web 应用程序时,您需要确保应用程序拥有完善的安全性特征补充.这里在谈到 Java 安全性时,我们并不谈及 Java 语言提供的安全性 API,也不涉及使用 Java 代码来保护应 ...