Tree

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

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

 
 //2017-08-09
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector> using namespace std; const int N = ;
int n, k, MAX, root, cnt, answer; //链式前向星
int head[N], tot;
struct Edge{
int next, to, w;
}edge[N<<]; void add_edge(int u, int v, int w){
edge[tot].w = w;
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++;
} int size[N];//size[i]表示以i为根的子树的大小,包括i。
int maxson[N];//maxson[i]表示以i为根的子树的最大儿子的大小。
int dis[N];//dis[i]表示i到根的距离。
bool vis[N];//vis[i]用来标记i点是否被删除。 void init(int n){
answer = ;
tot = ;
memset(vis, , sizeof(vis));
memset(head, -, sizeof(head));
} //计算出子树的大小
void dfs_size(int u, int fa){
size[u] = ;
maxson[u] = ;
for(int i = head[u]; ~i; i = edge[i].next){
int v = edge[i].to;
if(vis[v] || v == fa)continue;
dfs_size(v, u);
size[u] += size[v];
if(size[v] > maxson[u])
maxson[u] = size[v];
}
} //找子树的重心。最大子树最小的点即为树的重心。
void dfs_root(int r, int u, int fa){
if(size[r] - size[u] > maxson[u])//size[r]-size[u]为u上面的树的尺寸
maxson[u] = size[r] - size[u];
if(maxson[u] < MAX){
MAX = maxson[u];
root = u;
}
for(int i = head[u]; ~i; i = edge[i].next){
int v = edge[i].to;
if(vis[v] || v == fa)continue;
dfs_root(r, v, u);
}
} //计算出子树中每个点距离重心的距离
void dfs_dis(int u, int d, int fa){
dis[cnt++] = d;
for(int i = head[u]; ~i; i = edge[i].next){
int v = edge[i].to;
if(vis[v] || v == fa)continue;
dfs_dis(v, d+edge[i].w, u);
}
} //计算出以u为根的子树中距离和小于k的点对数
int cal(int u, int d){
int ans = ;
cnt = ;
dfs_dis(u, d, );
sort(dis, dis+cnt);
for(int i = , j = cnt-; i < j; i++){
while(dis[i]+dis[j] > k && i < j)//双指针
j--;
ans += j-i;
}
return ans;
} //分治,找到树的重心,分为经过重心的点对和不经过重心的点对。
void solve(int u){
MAX = n;
dfs_size(u, );
dfs_root(u, u, );
answer += cal(root, );
vis[root] = ;
for(int i = head[root]; ~i; i = edge[i].next){
int v = edge[i].to;
if(vis[v])continue;
answer -= cal(v, edge[i].w);
solve(v);
}
} int main()
{
//freopen("dataIn.txt", "r", stdin);
while(scanf("%d%d", &n, &k)!=EOF){
if(!n && !k)break;
int u, v, w;
init(n);
for(int i = ; i < n-; i++){
scanf("%d%d%d", &u, &v, &w);
add_edge(u, v, w);
add_edge(v, u, w);
}
solve();
printf("%d\n", answer);
} return ;
}

POJ1741(SummerTrainingDay08-G 树的点分治)的更多相关文章

  1. 【poj1741】Tree 树的点分治

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

  2. POJ1741 Tree(树的点分治)

    题目给一棵边带权的树,统计路径长度<=k的点对数. 楼教主男人八题之一,分治算法在树上的应用. 一开始看论文看不懂,以为重心和距离那些是一遍预处理得来的..感觉上不敢想每棵子树都求一遍重心和距离 ...

  3. POJ1741 Tree(树的点分治基础题)

    Give a tree with n vertices,each edge has a length(positive integer less than 1001).Define dist(u,v) ...

  4. POJ1741 Tree(树分治——点分治)题解

    题意:给一棵树,问你最多能找到几个组合(u,v),使得两点距离不超过k. 思路:点分治,复杂度O(nlogn*logn).看了半天还是有点模糊. 显然,所有满足要求的组合,连接这两个点,他们必然经过他 ...

  5. 牛客多校第三场 G Removing Stones(分治+线段树)

    牛客多校第三场 G Removing Stones(分治+线段树) 题意: 给你n个数,问你有多少个长度不小于2的连续子序列,使得其中最大元素不大于所有元素和的一半 题解: 分治+线段树 线段树维护最 ...

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

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

  7. hdu_5314_Happy King(树的点分治)

    题目链接:hdu_5314_Happy King 题意: 给出一颗n个结点的树,点上有权值: 求点对(x,y)满足x!=y且x到y的路径上最大值与最小值的差<=D: 题解: 还是树的点分治,在统 ...

  8. 【CF576E】Painting Edges 线段树按时间分治+并查集

    [CF576E]Painting Edges 题意:给你一张n个点,m条边的无向图,每条边是k种颜色中的一种,满足所有颜色相同的边内部形成一个二分图.有q个询问,每次询问给出a,b代表将编号为a的边染 ...

  9. 【bzoj3697】采药人的路径 树的点分治

    题目描述 给出一棵 $n$ 个点的树,每条边的边权为1或0.求有多少点对 $(i,j)$ ,使得:$i$ 到 $j$ 的简单路径上存在点 $k$ (异于 $i$ 和 $j$ ),使得 $i$ 到 $k ...

  10. 【bzoj3362/3363/3364/3365】[Usaco2004 Feb]树上问题杂烩 并查集/树的直径/LCA/树的点分治

    题目描述 农夫约翰有N(2≤N≤40000)个农场,标号1到N,M(2≤M≤40000)条的不同的垂直或水平的道路连结着农场,道路的长度不超过1000.这些农场的分布就像下面的地图一样, 图中农场用F ...

随机推荐

  1. C#6.0语言规范(九) 命名空间

    C#程序使用命名空间进行组织.命名空间既可以用作程序的“内部”组织系统,也可以用作“外部”组织系统 - 一种呈现暴露给其他程序的程序元素的方式. 提供了使用指令(使用指令)以便于使用命名空间. 编译单 ...

  2. 关于c++类的一些知识的总结

    1.经常会听到“类的声明.类的定义.类的实现”,它们之间有什么不一样? 经过查阅https://www.cnblogs.com/kkshaq/p/4660073.html博客的说法,类的声明是在.h文 ...

  3. 基于alpine用dockerfile创建的nginx镜像

    1.下载alpine镜像 [root@docker43 ~]# docker pull alpine Using default tag: latest Trying to pull reposito ...

  4. odoo开发笔记 -- 模型一对多tree视图弹窗效果实现

    实现效果参考: 1. 开发者模式 -- 设置 -- 工作流 -- 编辑 -- 添加项目 2. 会计模块 -- 管理 -- 付款条款 -- 编辑/创建 实现方式,很简单.只要视图界面写个一对多关联字段就 ...

  5. ActiveMq使用笔记

    java JMS技术 .1.   什么是JMS JMS即Java消息服务(Java Message Service)应用程序接口是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应用 ...

  6. eclipse maven jdk全局设置

    <profile> <id>jdk-1.8</id> <activation> <activeByDefault>true</acti ...

  7. 如何让你的网站用上免费的HTTPS

    因为之前网站上被注入了广告,再百般尝试之后最后还是使用了HTTPS解决了. 在实现HTTPS的时候最关键的就是证书. 证书的质量觉得了你被多少浏览器所信任. 证书的价格也就蹭蹭蹭往上涨了. 这里推荐一 ...

  8. Tomcat笔记:Tomcat的执行流程解析

    Bootstrap的启动 Bootstrap的main方法先new了一个自己的对象(Bootstrap),然后用该对象主要执行了四个方法: init(); setAwait(true); load(a ...

  9. 局域网的路由器&网卡

    网卡 唯一的标志 MAC地址:14:21:S8:8B:44:89 昵称:TP-Link-4489 如何获取局域网IP? DHCP(动态主机配置协议) DHCP 服务器可以动态的分配地址. 1)网卡(T ...

  10. AR介绍

    AR介绍 AR全名扩增实境,是一种实时融合现实与虚拟的图像技术. AR技术的三板斧:感知(寻找目标定位位置-与环境交互),渲染(实现产品交互-与客户交互),追踪(捕捉目标运动轨迹-客户环境上下文). ...