题目大意:
  给你一棵带权树,求出树中距离$\leq k$的点对个数。
思路:
  运用树上分治的思想,每次找出树的重心,考虑以下三种情况:
    1.两个结点在不同子树内,且距离$\leq k$,则算入答案中;
    2.两个结点距离$\leq k$,但属于同一棵子树中,需要被算入答案中,但考虑到以后会被子树的重心重新计算,故在这里忽略;
    3.两个结点距离$>k$,显然需要忽略。
  简而言之,就是每次统计最短路径经过重心的、距离$\leq k$的点对个数。
  我们可以每次先DP求出这棵子树的重心,再以这个重心为根,遍历整棵子树,将得到的离重心的距离存入一个数组中,然后枚举子树中的每个点对,将距离和$\leq k$的计入答案。
  考虑到要去除同一棵子树中的点对,我们需要在记录距离的同时,要记录每个结点所属的子树的编号,然后枚举的时候判断两个点是否属于统一子树即可。
  但是这样还是会TLE。
  考虑每次使用两个数组$a$和$b$,$a$存储当前子树各个结点的距离,$b$存储之前所有结点的距离,统计答案时只需要对$a$排序,然后枚举$b$中每个元素$b_i$,在$a$中二分查找小于等于$k-b_i$的元素个数即可。
  树上分治是$O(\log n)$的,排序是$O(n\log n)$的,因此总的时间复杂度是$O(n\log^2 n)$。

  1 #include<cstdio>
  2 #include<cctype>
  3 #include<vector>
  4 #include<cstring>
  5 #include<algorithm>
  6 inline int getint() {
  7     char ch;
  8     while(!isdigit(ch=getchar()));
  9     int x=ch^'0';
 10     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
 11     return x;
 12 }
 13 const int inf=0x7fffffff;
 14 const int V=10001;
 15 struct Edge {
 16     int to,w;
 17     Edge(const int to,const int w) {
 18         this->to=to;
 19         this->w=w;
 20     }
 21 };
 22 std::vector<Edge> e[V];
 23 inline void add_edge(const int u,const int v,const int w) {
 24     e[u].push_back(Edge(v,w));
 25 }
 26 int size[V];
 27 bool vis[V];
 28 int min_subtree_size,centroid,tree_size;
 29 void get_centroid(const int x,const int par) {
 30     size[x]=1;
 31     int max=0;
 32     for(unsigned i=0;i<e[x].size();i++) {
 33         int &y=e[x][i].to;
 34         if(vis[y]||y==par) continue;
 35         get_centroid(y,x);
 36         size[x]+=size[y];
 37         max=std::max(max,size[y]);
 38     }
 39     max=std::max(max,tree_size-size[x]);
 40     if(max<min_subtree_size) {
 41         min_subtree_size=max;
 42         centroid=x;
 43     }
 44 }
 45 int k;
 46 std::vector<int> dis,tdis;
 47 void get_dist(const int x,const int par,const int d) {
 48     if(d<=k) tdis.push_back(d);
 49     size[x]=1;
 50     for(unsigned i=0;i<e[x].size();i++) {
 51         int &y=e[x][i].to;
 52         if(vis[y]||y==par) continue;
 53         get_dist(y,x,d+e[x][i].w);
 54         size[x]+=size[y];
 55     }
 56 }
 57 int ans=0;
 58 inline void solve(const int x,const int sz) {
 59     tree_size=sz;
 60     min_subtree_size=inf;
 61     get_centroid(x,0);
 62     vis[centroid]=true;
 63     /*dis.clear();
 64     dis.push_back(Vertex(0,centroid));
 65     for(unsigned i=0;i<e[centroid].size();i++) {
 66         int &y=e[centroid][i].to;
 67         if(vis[y]) continue;
 68         get_dist(y,centroid,e[centroid][i].w,y);
 69     }
 70     std::sort(dis.begin(),dis.end());
 71     for(unsigned i=0;i<dis.size();i++) {
 72         for(unsigned j=i+1;j<dis.size();j++) {
 73             if(dis[i].d+dis[j].d>k) break;
 74             if(dis[i].root!=dis[j].root) ans++;
 75         }
 76     }*/
 77     dis.clear();
 78     dis.push_back(0);
 79     for(unsigned i=0;i<e[centroid].size();i++) {
 80         int &y=e[centroid][i].to;
 81         if(vis[y]) continue;
 82         tdis.clear();
 83         get_dist(y,centroid,e[centroid][i].w);
 84         std::sort(tdis.begin(),tdis.end());
 85         for(unsigned i=0;i<dis.size();i++) {
 86             ans+=std::upper_bound(tdis.begin(),tdis.end(),k-dis[i])-tdis.begin();
 87         }
 88         dis.insert(dis.end(),tdis.begin(),tdis.end());
 89     }
 90     int cur=centroid;
 91     for(unsigned i=0;i<e[cur].size();i++) {
 92         int &y=e[cur][i].to;
 93         if(vis[y]) continue;
 94         solve(y,size[y]);
 95     }
 96 }
 97 inline void init() {
 98     ans=0;
 99     memset(vis,0,sizeof vis);
100     for(int i=0;i<=V;i++) e[i].clear();
101 }
102 int main() {
103     for(;;) {
104         int n=getint();
105         k=getint();
106         if(!n&&!k) return 0;
107         init();
108         for(int i=1;i<n;i++) {
109             int u=getint(),v=getint(),w=getint();
110             add_edge(u,v,w);
111             add_edge(v,u,w);
112         }
113         solve(1,n);
114         printf("%d\n",ans);
115     }
116 }

转载于:https://www.cnblogs.com/skylee03/p/7470625.html

[POJ1741]Tree相关推荐

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

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

  2. POJ1741 Tree 树中点对统计【树分治入门】

    算法合集之<分治算法在树的路径问题中的应用> 论文下载地址 树被定义为没有圈的连通图,有几个性质 在树中去掉一条边后,得到的图是不连通的 在树中添加一条边后,一定存在一条边 树的每一对顶点 ...

  3. poj1741 Tree 点分治

    入门题,算是对树分治有了初步的理解吧. #include<iostream> #include<cstdio> #include<cstring> #include ...

  4. POJ1741 Tree(点分治)

    嘟嘟嘟 没错,这一道最经典的点分治模板题. 题意:求树上两点间距离\(\leqslant k\)的点对个数. 点分治这东西我好早就听说了,然后一两个月前也学了一下,不过只是刷了个模板,没往深处学. 对 ...

  5. [poj1741 Tree]树上点分治

    题意:给一个N个节点的带权树,求长度小于等于K的路径条数 思路:选取一个点作为根root,假设f(root)是当前树的答案,那么答案来源于两部分: (1)路径不经过root,那么就是完全在子树内,这部 ...

  6. [poj1741]tree 解题报告

    经典的点分做法就不说了(然而我写点分t了..) 线段树/平衡树启发式合并的话,就是维护子树每个节点到子树跟的距离,打一个整棵子树的标记,然后按dfs/bfs序启发式合并,合并之前先查询一下答案即可. ...

  7. 【楼天城男人八题】【树分治|Treap+启发式合并】POJ1741 Tree

    题面在这里 待我先膜拜一下楼教主-- 首先这题是很明显的树分治 想说点什么却发现已经没什么好说了 然后我们来看另一种解法:平衡树乱搞 这里用的是Treap实现 对于每个节点,用Treap记录该子树每个 ...

  8. POJ1741 Tree(树分治)

    题意: 求树上距离小于等于K的点对有多少个 思路: 每次分治,我们首先算出重心,为了计算重心,需要进行两次dfs,第一次把以每个结点为根的子树大小求出来,第二次是从这些结点中找重心 找到重心后,需要统 ...

  9. POJ1741:Tree——题解+树分治简要讲解

    http://poj.org/problem?id=1741 题目大意:给一棵树,求点对间距离<=k的个数. -------------------- 以这道题为例记录一下对于树分治的理解. 树 ...

最新文章

  1. 新华网泸州分频道报道IT诗人
  2. 云原生系列「三」容器网络
  3. JDK / JRE zip
  4. 液滴型单细胞测序技术比较(二)
  5. oracle 学习之:建视图时报ora-01031
  6. 算法笔记_094:蓝桥杯练习 矩阵相乘(Java)
  7. ubuntu安装rpm的方法
  8. paip.提升用户体验---论文本编辑器的色彩方案
  9. 3dmax渲染大图高清最详细参数来了
  10. python项目运行的软硬件环境_开发时的软硬件环境和运行时的软硬件环境分别是什么...
  11. 图像相似的算法有哪些,图像相似的算法是什么
  12. tomcat中的过滤器
  13. 数据结构 基于字符串模式匹配算法的病毒感染检测问题
  14. 微服务架构的深入理解-总结的很好
  15. [Unity] 制作游戏 小球爱碰撞
  16. 【C语言】BC62统计数据正负数个数(DAY 4)
  17. 基于粒子群算法的微电网优化调度应用研究(三、长短期记忆网络和卷积神经网络预测模型)
  18. 百度搜索为什么这么快?
  19. 奔驰激活carplay手机互联系统编程改装 成都蔚一名车汇
  20. 迭代器模式实例与解析---实例:电视机遥控器

热门文章

  1. 基于群集的Hyper-v Server副本
  2. 离ExtJS 4.1 beta发布只剩26个bug了
  3. 基于最优化方法的超宽带通信信号设计
  4. deeplearning 重要调参参数分析
  5. Oracle 之 配置HugePages内存
  6. windows路径操作API函数
  7. Access中复制表
  8. android 启动其它apk
  9. 用了N年的接口,你知道接口是什么吗?——一个简单实例说明接口的伟大意义...
  10. BIND9配置文件详解模板