Tree
Time Limit: 1000MS   Memory Limit: 30000K
Total Submissions: 20816   Accepted: 6820

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

Source

【分析】

给一棵边带权树,问两点之间的距离小于等于K的点对有多少个。

将无根树转化成有根树进行观察。满足条件的点对有两种情况:两个点的路径横跨树根,两个点位于同一颗子树中。

如果我们已经知道了此时所有点到根的距离a[i],a[x] + a[y] <= k的(x, y)对数就是结果,这个可以通过排序之后O(n)的复杂度求出。然后根据分治的思想,分别对所有的儿子求一遍即可,但是这会出现重复的——当前情况下两个点位于一颗子树中,那么应该将其减掉(显然这两个点是满足题意的,为什么减掉呢?因为在对子树进行求解的时候,会重新计算)。

在进行分治时,为了避免树退化成一条链而导致时间复杂度变为O(N^2),每次都找树的重心,这样,所有的子树规模就会变的很小了。时间复杂度O(Nlog^2N)。

树的重心的算法可以线性求解。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <time.h>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#define met(a,b) memset(a,b,sizeof a)
#define pb push_back
#define lson(x) ((x<<1))
#define rson(x) ((x<<1)+1)
using namespace std;
typedef long long ll;
const int N=1e5+;
const int M=1e6+;
int n,m,k,tot,size,root,ans;
int head[N],s[N],f[N],d[N];
bool done[N];
vector<int>dep;
struct man{
int to,next,l;
}edg[N*];
void add(int u,int v,int l){
edg[tot].to=v;edg[tot].l=l;edg[tot].next=head[u];head[u]=tot++;
}
void getroot(int u,int fa){
s[u]=;f[u]=;
for(int i=head[u];i!=-;i=edg[i].next){
int v=edg[i].to;
if(v!=fa&&!done[v]){
getroot(v,u);
s[u]+=s[v];
f[u]=max(f[u],s[v]);
}
}
f[u]=max(f[u],size-s[u]);
if(f[u]<f[root])root=u;
}
void getdep(int u,int fa){
dep.push_back(d[u]);
s[u]=;
for(int i=head[u];i!=-;i=edg[i].next){
int v=edg[i].to;
if(v!=fa&&!done[v]){
d[v]=d[u]+edg[i].l;
getdep(v,u);
s[u]+=s[v];
}
}
}
int calc(int u,int init){
dep.clear();
d[u]=init;
getdep(u,);
sort(dep.begin(),dep.end());
int ret=;
for(int l=,r=dep.size()-;l<r; ){
if(dep[l]+dep[r]<=k)ret+=r-l++;
else r--;
}
return ret;
}
void work(int u){
ans+=calc(u,);
done[u]=true;
for(int i=head[u];i!=-;i=edg[i].next){
int v=edg[i].to;
if(!done[v]){
ans-=calc(v,edg[i].l);
f[]=size=s[v];
getroot(v,root=);
work(root);
}
}
}
int main(){
while(~scanf("%d%d",&n,&k)&&n&&k){
tot=ans=;f[]=size=n;
met(head,-);met(done,false);
int u,v,l;
for(int i=;i<n;i++){
scanf("%d%d%d",&u,&v,&l);
add(u,v,l);add(v,u,l);
}
getroot(,root=);
work(root);
printf("%d\n",ans);
}
return ;
}

POJ 1741 Tree (点分治)的更多相关文章

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

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

  2. POJ 1741 Tree 树分治

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

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

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

  4. POJ 1741 Tree(点分治点对<=k)

    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(树的点分治)

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

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

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

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

                                                                                                 POJ 174 ...

随机推荐

  1. dnsmasq-2.48没有ipset特性,安装dnsmasq-2.71来支持ipset

    iptables只能根据ip地址进行转发,不能识别域名,而dnsmasq-full不仅可以实现域名-IP的映射,还可以把这个映射关系存储在ipset中,所以使用dnsmasq+ipset就可以实现ip ...

  2. Idea 怎么远程debug

    注意的问题:远程debug别人的服务器只能开一个debug,所以当你的同事比你先远程debug同一台服务器时,你应该报Error running 某某ip地址 .unable to open debu ...

  3. JAVASCRIPT和JSP计算闰年

    0x01:JAVASCRIPT 实现 <h1 align="left">求闰年</h1> 开始年份: <input type="text&q ...

  4. react 记录:运行npm run eject命令暴露配置文件都报这个错误

    问题: react 使用create-react-app命令创建一个项目,运行npm run eject命令暴露配置文件都报这个错误 原因:主要是脚手架添加 .gitgnore文件,但是却没有本地仓库 ...

  5. javascript中的递增递减操作符

    javascript中递增递减属于一元操作符,所谓一元操作符,即只能操作一个值的操作符. 递增和递减操作符各有两个版本:前置型和后置型.顾名思义,前置型应该位于要操作的变量之前,而后置型应该位于要操作 ...

  6. Ueditor 1.4.3 插入表格后无边框无颜色,不能正常显示

    在使用Ueditor 插入表格的功能时,发现插入时正常. 但保存到后台后再取出来,表格不能正常显示.查看保存的html代码,发现保存时并未给table 添加border属性.以致于再次取出来时,不能正 ...

  7. Windows下使用批处理实现启动关闭mysql_DOS/BAT

    cls @echo off :设置窗口字体颜色 color 0a :设置窗口标题 TITLE MySQL管理程序 by ThinkVenus call :checkAdmin goto menu :菜 ...

  8. 【CF24D】Broken Robot (DP+高斯消元)

    题目链接 题意:给定一个\(n\times m\)的矩阵,每次可以向→↓←移动一格,也可以原地不动,求从\((x,y)\)到最后一行的期望步数. 此题标签\(DP\) 看到上面这个肯定会想到 方法一: ...

  9. POJ2680(动态规划,大数)

    Computer Transformation Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4548   Accepted ...

  10. HDU1503(LCS,记录路径)

    Advanced Fruits Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)T ...