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. 敏捷冲刺每日报告——Day3

    1.情况简述 Alpha阶段第一次Scrum Meeting 敏捷开发起止时间 2017.10.27 00:00 -- 2017.10.28 00:00 讨论时间地点 2017.10.27晚9:30, ...

  2. 项目Beta预备

    项目名称:城市安全风险管控系统 Beta预备: 讨论组长是否重选的议题和结论 项目组长可以说是一个团队的灵魂和核心.一个好的领导者可以激发团队成员的工作热情,提高开发效率,保质保量的完成工作.虽然在A ...

  3. iOS开发-OC中TabView的编辑

    UITableView编辑 1> UITableView 编辑流程 2> UITableView 编辑步骤(四步) ① 第一步 : 让 TableView 处于编辑状态(在按钮点击事件方法 ...

  4. 手把手教你 LabVIEW 串口仪器控制——VISA 驱动下载安装篇

           仪器控制,核心在于 VISA 函数..有些仪器可能不需要 VISA,有自己的 DLL 什么的,我就管不着.        正常情况下,大家安装的 LabVIEW,都是不带 VISA 驱动 ...

  5. 《高级软件测试》web测试实践--12月30日记录

    考完数学,我们正式开始web测试实践的作业,今天,我们主要进行了方案的选择和人员的分工.任务计划和安排如上图所示. 任务进展:完成题目选择和人员分工: 遇到问题:暂无: 下一步任务:完成软件评测.用户 ...

  6. bzoj千题计划214:bzoj3589: 动态树

    http://www.lydsy.com/JudgeOnline/problem.php?id=3589 树链剖分 用线段数维护扫描线的方式来写,标记只打不下传 #include<cstdio& ...

  7. Leetcode:Two Sum

    原题:https://leetcode.com/problems/two-sum/ 尝试了两种方法: 方法一: var twoSum = function(nums, target) { for(va ...

  8. hadoop2.6.0实践:003 检查hadoop是否可用

    start-dfs.sh start-yarn.sh 1.检查hdfs hdfs dfs -ls / http://localhost:50070 2.运行例子程序 hdfs dfs -ls / hd ...

  9. gradle入门(1-1)gradle的概念和使用

    一.Gradle是什么 Gradle是一种Java应用构建工具,它采用领域特定语言 Groovy 语法实现配置. 1.Gradle的基本概念 项目:项目的配置 即 build.gradle. 任务:任 ...

  10. maven入门(1-1)maven是什么?

    Maven是一个项目管理工具,它包含了 一个项目对象模型 (Project Object Model), 一组标准集合, 一个项目生命周期(Project Lifecycle), 一个依赖管理系统(D ...