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
题目分析 : 给定一棵树,以及树上边的关系大小,问你又多少对点的距离是小于等于所给定的 d 的
思路分析 : 树上点分治的板子题,首先寻找树的重心,以重心为根结点,寻求所有符合题意要求的点对,但是这样计算会算出一些不符合题目的点对,在减去即可,此时当遍历到一个新的结点时,此时的情况又可以当成最初的情况,找重心的时候要注意,对它的子树来说,总的结点数是小于 n 的!!!
      最后的复杂度是n logn logn    其中每次快排是nlogn 而递归的深度为logn
代码示例 :
const int maxn = 1e4+5;
const int inf = 0x3f3f3f3f;
#define ll long long int n, m;
struct node
{
int to, cost;
node(int _to = 0, int _cost = 0):to(_to), cost(_cost){}
};
vector<node>ve[maxn];
int root;
int size[maxn], mx[maxn]; // size表示每个结点所连的结点数, mx表示对每个根结点所连的最大结点子树有多少的结点
int balance;
bool done[maxn];
int ans = 0;
int numm; // 表示结点总数 void getroot(int x, int fa){
size[x] = 1, mx[x] = 0; for(int i = 0; i < ve[x].size(); i++){
int to = ve[x][i].to;
if (to == fa || done[to]) continue;
getroot(to, x);
size[x] += size[to];
mx[x] = max(mx[x], size[to]);
}
mx[x] = max(mx[x], numm-size[x]); // 对子树在寻找子树的重心的过程中,子树的总结点数是会变小的
if (mx[x] < balance) {balance = mx[x], root = x;}
} int cnt = 0;
int dep[maxn];
void dfssize(int x, int fa, int d){
dep[cnt++] = d; for(int i = 0; i < ve[x].size(); i++){
int to = ve[x][i].to;
int cost = ve[x][i].cost;
if (to == fa || done[to]) continue;
dfssize(to, x, d+cost);
}
} int cal(int x, int d){
cnt = 0;
dfssize(x, x, d);
sort(dep, dep+cnt);
int l = 0, r = cnt-1;
int sum = 0; while(l < r){
if (dep[l]+dep[r] <= m){
sum += r-l;
l++;
}
else r--;
}
//printf("sum = %d \n", sum);
//system("pause");
return sum;
} void dfs(int x){
done[x] = true;
ans += cal(x, 0); for(int i = 0; i < ve[x].size(); i++){
int to = ve[x][i].to;
int cost = ve[x][i].cost; if (done[to]) continue;
ans -= cal(to, cost);
balance = inf;
numm = size[to]; // 这里是重点,因为这个地方一直T,还以为写的代码有问题
getroot(to, to);
//printf("root = %d\n", root);
dfs(root);
}
} int a, b, w;
int main() {
while(scanf("%d%d", &n, &m) && n+m){
for(int i = 0; i <= 10000; i++) ve[i].clear();
memset(done, false, sizeof(done));
for(int i = 1; i < n; i++){
scanf("%d%d%d", &a, &b, &w);
ve[a].push_back(node(b, w));
ve[b].push_back(node(a, w));
}
ans = 0;
balance = inf;
numm = n;
getroot(1, 1);
//printf("root = %d\n", root);
dfs(root);
printf("%d\n", ans);
}
return 0;
}

树上点分治 poj 1741的更多相关文章

  1. 点分治——POJ 1741

    写的第一道点分治的题目,权当认识点分治了. 点分治,就是对每条过某个点的路径进行考虑,若路径不经过此点,则可以对其子树进行考虑. 具体可以看menci的blog:点分治 来看一道例题:POJ 1741 ...

  2. 树分治 poj 1741

    n k n个节点的一棵树 k是距离 求树上有几对点距离<=k; #include<stdio.h> #include<string.h> #include<algo ...

  3. POJ 1741 Tree 树上点分治

    题目链接:http://poj.org/problem?id=1741 题意: 给定一棵包含$n$个点的带边权树,求距离小于等于K的点对数量 题解: 显然,枚举所有点的子树可以获得答案,但是朴素发$O ...

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

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

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

                                                                                                 POJ 174 ...

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

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

  7. poj 1741 树的点分治(入门)

    Tree Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 18205   Accepted: 5951 Description ...

  8. poj 1741 Tree(树的点分治)

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

  9. poj 1741 楼教主男人八题之中的一个:树分治

    http://poj.org/problem? id=1741 Description Give a tree with n vertices,each edge has a length(posit ...

随机推荐

  1. TSLint-Angular 配置

    代码风格和语义的检查工具,帮助规范 TS 和 Angular 代码书写: 安装: => cnpm install // 安装相关依赖 全局安装 cnpm install -g tslint ty ...

  2. 【codeforces 766C】Mahmoud and a Message

    time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...

  3. Python--day32--struct模块定制报头理论(什么是网络协议?网络协议的本质是什么?)

  4. js基础——变量、作用域、内存

    1.new关键字创建的是引用类型: eg. var box = new Object();      box.name = "Linda";//引用类型添加属性没问题     al ...

  5. Yet Another Number Sequence——[矩阵快速幂]

    Description Everyone knows what the Fibonacci sequence is. This sequence can be defined by the recur ...

  6. POJ 1511 Invitation Cards(逆向思维 SPFA)

    Description In the age of television, not many people attend theater performances. Antique Comedians ...

  7. vuejs 数据视图不更新

    由于 JavaScript 的限制,Vue 不能检测对象属性的添加或删除 可以使用 Vue.set(object, key, value) 方法向嵌套对象添加响应式属性 数组 this.$set(ar ...

  8. 【一起学源码-微服务】Nexflix Eureka 源码八:EurekaClient注册表抓取 精妙设计分析!

    前言 前情回顾 上一讲 我们通过单元测试 来梳理了EurekaClient是如何注册到server端,以及server端接收到请求是如何处理的,这里最重要的关注点是注册表的一个数据结构:Concurr ...

  9. 将 Sidecar 容器带入新的阶段

    作者 | 徐迪.张晓宇 导读:本文根据徐迪和张晓宇在 KubeCon NA 2019 大会分享整理.分享将会从以下几个方面进行切入:首先会简单介绍一下什么是 Sidecar 容器:其次,会分享几个阿里 ...

  10. Z字形变换 leetcode 6

    一.按行存储 1.解题思路 1.通过当前行的不断上下循环移动 2.将字符按序存放入vector中 3.最后再按行取出 2.代码及注释 class Solution { public: string c ...