题目大意:给出一颗无根树和每条边的权值,求出树上两个点之间距离<=k的点的对数。

思路:树的点分治。利用递归和求树的重心来解决这类问题。由于满足题意的点对一共仅仅有两种:

1.在以该节点的子树中且不经过该节点。

2.路径经过该节点。

对于第一种点,我们递归处理;另外一种点。我们能够将全部子树的节点到这个子树的根节点的距离处理出来,然后排序处理出满足要求的点对的个数。

依照正常的树的结构来切割子树,这种做法的时间复杂度肯定是不好看的,为了让子树大小尽量同样。我们每次处理这个子树前找到这个子树的重心,把这个重心当为根,然后在切割子树,这样时间复杂度最坏会降到O(nlog^2n)。

CODE:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 20010
#define INF 0x3f3f3f3f
using namespace std; int points,edges,k;
int head[MAX],total;
int next[MAX << 1],aim[MAX << 1],length[MAX << 1]; int cnt[MAX],c; //每一个子树中经过根节点的满足条件的对数
int size[MAX],_size,dis[MAX],p;
int _total;
bool v[MAX]; inline void Initialize();
inline void Add(int x,int y,int len);
void Work(int x);
void GetRoot(int x,int last);
inline int Count(int x,int len);
void GetDis(int x,int last,int len); int main()
{
while(scanf("%d%d",&points,&k),points + k) {
Initialize();
for(int x,y,z,i = 1;i < points; ++i) {
scanf("%d%d%d",&x,&y,&z);
Add(x,y,z),Add(y,x,z);
}
Work(1);
int ans = 0;
for(int i = 1;i <= points; ++i)
ans += cnt[i];
printf("%d\n",ans);
}
return 0;
} inline void Initialize()
{
total = 0;
memset(head,0,sizeof(head));
memset(v,false,sizeof(v));
} inline void Add(int x,int y,int len)
{
next[++total] = head[x];
aim[total] = y;
length[total] = len;
head[x] = total;
} void Work(int x)
{
_size = INF;
_total = size[x] ? size[x]:points;
GetRoot(x,0);
x = c;
v[x] = true;
cnt[x] = Count(x,0);
for(int i = head[x];i;i = next[i]) {
if(v[aim[i]]) continue;
cnt[x] -= Count(aim[i],length[i]);
Work(aim[i]);
}
} void GetRoot(int x,int last)
{
size[x] = 1;
int max_size = 0;
for(int i = head[x];i;i = next[i]) {
if(v[aim[i]] || aim[i] == last) continue;
GetRoot(aim[i],x);
size[x] += size[aim[i]];
max_size = max(max_size,size[aim[i]]);
}
max_size = max(max_size,_total - size[x]);
if(max_size < _size)
_size = max_size,c = x;
} inline int Count(int x,int len)
{
int re = 0;
p = 0;
GetDis(x,0,len);
sort(dis,dis + p);
int l = 0,r = p - 1;
while(l < r) {
if(dis[l] + dis[r] <= k)
re += (r - l),l++;
else r--;
}
return re;
} void GetDis(int x,int last,int len)
{
dis[p++] = len;
for(int i = head[x];i;i = next[i]) {
if(aim[i] == last || v[aim[i]]) continue;
GetDis(aim[i],x,len + length[i]);
}
}

POJ 1741 Tree 树的分治(点分治)的更多相关文章

  1. poj 1741 Tree (树的分治)

    Tree Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 30928   Accepted: 10351 Descriptio ...

  2. POJ 1741.Tree 树分治 树形dp 树上点对

    Tree Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 24258   Accepted: 8062 Description ...

  3. POJ 1741 Tree 树的分治

    原题链接:http://poj.org/problem?id=1741 题意: 给你棵树,询问有多少点对,使得这条路径上的权值和小于K 题解: 就..大约就是树的分治 代码: #include< ...

  4. POJ 1741 Tree 树分治

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

  5. POJ 1741 Tree(树的点分治,入门题)

    Tree Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 21357   Accepted: 7006 Description ...

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

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

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

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

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

                                                                                                 POJ 174 ...

  9. POJ 1741 Tree (树的分治,树的重心)

    题意:给一棵树,n个节点,给定一个数k,求任意满足dist(a,b)<=k的点对的数量. 思路: 这道题的思路比较简单,但是细节很多. 此题可以用分治法,如何分治? (1)如果path(a,b) ...

随机推荐

  1. Spring Boot 启动的时候遇到 java.lang.ClassNotFoundException: ch.qos.logback.classic.Level

    在刚开始接触spring boot的时候,想创建一个Hello World 的project. 但是创建完之后,Run as 'Spring Boot APP'的时候遇到这个错误. Level类存在于 ...

  2. thinkphp 多个字段的不同关系的查询条件实现 .

    tp的$map不同条件默认是 and ,如果要用or<><><><>如下 例如查询Stu表中年龄大于18,或者身高低于180cm的男性(1为男性),(例 ...

  3. 2015 Multi-University Training Contest 7 hdu 5379 Mahjong tree

    Mahjong tree Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Tota ...

  4. java中Collection 与Collections的区别

    1. Collection是集合类的一个顶级接口,其直接继承接口有List与Set 而Collections则是集合类的一个工具类/帮助类,其中提供了一系列静态方法,用于对集合中元素进行排序.搜索以及 ...

  5. intellij idea 打开两个 terminal

    intellij idea 打开两个  terminal alt+f12可以打开terminal,在terminal窗口左侧点击绿色的加号,就可以又打开一个terminal,用tab标签展示:

  6. Extjs4.2 ajax请求url中传中文參数乱码问题

    今天有个需求须要在url中传入中文參数.结果在后台取得时出现乱码,怀疑可能是编码问题.上网查询了资料,试了几种办法.发现有一种可行,记录在此,以便查阅. url中用encodeURI 进行2次编码: ...

  7. hdu 2604 Queuing (矩阵高速幂)

    Queuing Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total S ...

  8. RT-Thread开篇

    一直以来对操作系统都有一种既仰慕又畏惧的情感.一方面被操作系统的强大深深吸引.还有一方面又被操作系统的复杂性感到畏惧. 记得在学校的时候也学过一些操作系统的理论知识,但也只限于理论,更似人云亦云. 本 ...

  9. 公布自己的pods到CocoaPods trunk 及问题记录

    这两天准备把之前写的一些小玩意加入到pods库中去,參考了一些资料后进行操作,实际中也遇到了一些问题,记录下来.问题及解决方案在后面. 參考内容转载例如以下: 首先更新了用trunk之后,CocoaP ...

  10. iOS 自己主动登录,登录过程中一直显示载入页

    iOS开发中 假设client做的人性化一点肯定会考虑自己主动登录 事实上原理非常easy,就是再首次登录成功之后将username和password存入userdefault 下次登录的时候推断us ...