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. 2019-2-28-C#-16-进制字符串转-int-

    title author date CreateTime categories C# 16 进制字符串转 int lindexi 2019-02-28 11:51:36 +0800 2018-04-2 ...

  2. 2018-2-13-wpf-使用-Dispatcher.Invoke-冻结窗口

    title author date CreateTime categories wpf 使用 Dispatcher.Invoke 冻结窗口 lindexi 2018-2-13 17:23:3 +080 ...

  3. win10 uwp 好看的时间选择控件

    本文告诉大家我找到的好看的时间选择控件 先给大家看一下图,然后就知道我说的是什么 首先需要安装 Nuget ,搜索 DeanChalk.UWP.TimePicker 或输入Install-Packag ...

  4. CodeForce - 1187 E. Tree Painting (换根dp)

    You are given a tree (an undirected connected acyclic graph) consisting of nn vertices. You are play ...

  5. springcloud玩转单点登录【oauth】

    随着公司项目的庞大,单点登录变得尤为重要,那么怎么实现单点登录,下面已oauth为标准实现单点登录. [特别鸣谢:魔乐科技,附上官网:www.mldn.cn] 1:项目组织结构 本项目为oAuth修改 ...

  6. python内置模块(python标准库)

    1.time模块 掌握下面三种方式的转换 文件名不能跟系统内置模块重名!   #三种方式的转化关系 #时间戳(timestamp): 为了计时 为了减法计算   import time print(t ...

  7. react-native-vector-icons 安装、使用

    react-native-vector-icons 安装.使用 前言 任何库的安装与使用都离不开官文,按照官方文档一步步操作可以规避大多数问题.不过很多库只有英文文档,想要完全参透需要时间.react ...

  8. mysql中information_schema.triggers字段说明

    1. 获取所有触发器信息(TRIGGERS) SELECT  *  FROM information_schema.TRIGGERS WHERE  TRIGGER_SCHEMA='数据库名';  TR ...

  9. CodeForces - 1239A

    推公式题,万万没想到斐波那契啊

  10. C# 字段与属性的区别

    在C#中,我们可以非常自由的.毫无限制的访问公有字段, 但在一些场合中,我们可能希望限制只能给字段赋于某个范围的值.或是要求字段只能读或只能写, 或是在改变字段时能改变对象的其他一些状态,这些单靠字段 ...