Tree
Time Limit: 1000MS   Memory Limit: 30000K
Total Submissions: 25286   Accepted: 8421

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

点分治

点分治通常用以解决树上的分治问题,以点为界分治。【我做题还不够多,先不详细讲,之后再总结
这道题要求所有d(u,v) <= k的对数,直接枚举肯定不行,我们先求出路径经过树上一点的路径数

如何求通过一点的路径数?
我们以该点为根并求出树中所有点到根的距离,再全部排序,用双指针的方法O(n)统计d[u] + d[v] <= k的对数ans1
但是会将都在同一个子树,也就是不经过根的路径也算上,再对每一个子树算一遍ans2减去就好了
就是ans1 - ∑ans2

之后再向下分治,向每颗子树递归。

为防止极端数据,我们每次求出重心为根
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long int
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define Redge(u) for (int k = head[u]; k != -1; k = edge[k].next)
using namespace std;
const int maxn = 10005,maxm = 40005,INF = 1000000000;
inline int RD(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57) {if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57) {out = (out << 1) + (out << 3) + c - '0'; c = getchar();}
return out * flag;
}
int N,K,vis[maxn],head[maxn],d[maxn],dep[maxn],nedge = 0,F[maxn],Siz[maxn],rt = 0,n,ans;
struct EDGE{int to,w,next;}edge[maxm];
inline void build(int u,int v,int w){
edge[nedge] = (EDGE){v,w,head[u]}; head[u] = nedge++;
edge[nedge] = (EDGE){u,w,head[v]}; head[v] = nedge++;
}
void getRT(int u,int fa){
int to; F[u] = 0; Siz[u] = 1;
Redge(u) if ((to = edge[k].to) != fa && !vis[to]){
getRT(to,u);
Siz[u] += Siz[to];
F[u] = max(F[u],Siz[to]);
}
F[u] = max(F[u],n - Siz[u]);
if (F[u] < F[rt]) rt = u;
}
void getdep(int u,int fa){
dep[++dep[0]] = d[u]; int to;
Redge(u) if (!vis[to = edge[k].to] && to != fa){
d[to] = d[u] + edge[k].w;
getdep(to,u);
}
}
int cal(int u,int D){
d[u] = D; dep[0] = 0;
getdep(u,0);
sort(dep + 1,dep + 1 + dep[0]);
int l = 1,r = dep[0],t = 0;
while (l < r)
if (dep[l] + dep[r] <= K) t += r - l++;
else r--;
return t;
}
void solve(int u){
ans += cal(u,0);
vis[u] = true; int to;
Redge(u) if (!vis[to = edge[k].to]){
ans -= cal(to,edge[k].w);
n = Siz[to]; rt = 0;
getRT(to,rt);
solve(rt);
}
}
int main(){
while (true){
memset(head,-1,sizeof(head));
memset(vis,0,sizeof(vis));
int a,b,w; N = RD(); K = RD(); ans = 0; rt = 0; nedge = 0;
if (!N) break;
REP(i,N - 1){
a = RD(); b = RD(); w = RD();
build(a,b,w);
}
n = N; F[0] = INF;
getRT(1,0);
solve(rt);
printf("%d\n",ans);
}
return 0;
}

POJ1741 tree 【点分治】的更多相关文章

  1. [POJ1741]Tree(点分治)

    树分治之点分治入门 所谓点分治,就是对于树针对点的分治处理 首先找出重心以保证时间复杂度 然后递归处理所有子树 对于这道题,对于点对(u,v)满足dis(u,v)<=k,分2种情况 路径过当前根 ...

  2. [poj1741]Tree(点分治+容斥原理)

    题意:求树中点对距离<=k的无序点对个数. 解题关键:树上点分治,这个分治并没有传统分治的合并过程,只是分成各个小问题,并将各个小问题的答案相加即可,也就是每层的复杂度并不在合并的过程,是在每层 ...

  3. [bzoj1468][poj1741]Tree[点分治]

    可以说是点分治第一题,之前那道的点分治只是模模糊糊,做完这道题感觉清楚了很多,点分治可以理解为每次树的重心(这样会把数分为若干棵子树,子树大小为log级别),然后统计包含重心的整个子树的值减去各个子树 ...

  4. POJ1741 Tree 树分治模板

    http://poj.org/problem?id=1741   题意:一棵n个点的树,每条边有距离v,求该树中距离小于等于k的点的对数.   dis[y]表示点y到根x的距离,v代表根到子树根的距离 ...

  5. POJ1741 Tree + BZOJ1468 Tree 【点分治】

    POJ1741 Tree + BZOJ1468 Tree Description Give a tree with n vertices,each edge has a length(positive ...

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

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

  7. [poj1741][tree] (树/点分治)

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

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

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

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

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

随机推荐

  1. CRL2.1更新

    增加没有主键ID的抽象类,使能自义主键字段实现MODEL抽象类定义结构为 /// <summary> /// 基类,不包含任何字段 /// 如果有自定义主键名对象,请继承此类型 /// & ...

  2. 「日常训练」Kefa and Company(Codeforces Round #321 Div. 2 B)

    题意与分析(CodeForces 580B) \(n\)个人,告诉你\(n\)个人的工资,每个人还有一个权值.现在从这n个人中选出m个人,使得他们的权值之和最大,但是对于选中的人而言,其他被选中的人的 ...

  3. hdu2509Be the Winner(反nim博弈)

    Be the Winner Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tot ...

  4. lintcode 平面列表

    问题描述: 给定一个列表,该列表中的每个要素要么是个列表,要么是整数.将其变成一个只包含整数的简单列表. 样例: 给定 [1,2,[1,2]],返回 [1,2,1,2]. 给定 [4,[3,[2,[1 ...

  5. 关于javascript的一个小问题,请问有人看出啥问题吗?

    最近学习javascript,有一个问题挺奇怪的,先贴出代码: function binarySearch(){ var arr = [0,1,2,3]; var res = actbinarySea ...

  6. spring java config 初探

    Java Config 注解 spring java config作为同xml配置形式的另一种表达形式,使用的场景越来越多,在新版本的spring boot中 大量使用,今天我们来看下用到的主要注解有 ...

  7. 水管工游戏:dfs(递归)

    添柴网这题好想不能评测,所以不确保代码的正确性 题目描述: 这小节有点难,看不太懂可以跳过哦.最近小哼又迷上一个叫做水管工的游戏.游戏的大致规则是这样的.一块矩形土地被分为N * M的单位正方形,现在 ...

  8. python SyntaxError: Non-ASCII character '\xe8' in file C:\Users\nwpujun\PycharmProjects\projects\hrl1\hrlAgent\src\li_nn.py on line 52

    解决方法:在文件头部加上这样的一句话 # -*- coding: utf-8 -*- 注意:加在其他的位置可能没用,我就是这样的

  9. 解读:未来30年新兴科技趋势报告(AI Frist,IoT Second)

    前段时间美国公布的一份长达35页的<未来30年新兴科技趋势报告>.该报告是在美国过去五年内由政府机构.咨询机构.智囊团.科研机构等发表的32份科技趋势相关研究调查报告的基础上提炼形成的. ...

  10. Switches and Lamps(思维)

    You are given n switches and m lamps. The i-th switch turns on some subset of the lamps. This inform ...