题意:给一个N个节点的带权树,求长度小于等于K的路径条数

思路:选取一个点作为根root,假设f(root)是当前树的答案,那么答案来源于两部分:

(1)路径不经过root,那么就是完全在子树内,这部分可以递归统计

(2)路径经过root,这部分可以通过容斥原理统计,具体见有关点分治资料。。。

点分治有个特点,当考虑的问题由根这个子树转为儿子的子树时,可以选取任意点作为新的根,只要它在儿子的子树内,这就使得我们可以通过选取特别的点使得树深度更小,这个点就是树的重心(在程序里面是不断找子树的重心),树分治的复杂度是O(NH+TH)的,其中H是树的深度,T是每层计算答案的复杂度,重心可以将树的深度变成O(logN)。

另外,整体看树分治的遍历节点的过程,发现它与建堆的过程十分相似,也就从侧面说明了树分治的复杂度。。。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <map>
#include <vector>
using namespace std;
#define X first
#define Y second
#define pb(x) push_back(x)
#define mp(x, y) make_pair(x, y)
#define all(a) (a).begin(), (a).end()
#define mset(a, x) memset(a, x, sizeof(a))
#define mcpy(a, b) memcpy(a, b, sizeof(b))
#define cas() int T, cas = 0; cin >> T; while (T --)
template<typename T>bool umax(T&a, const T&b){return a<b?(a=b,true):false;}
template<typename T>bool umin(T&a, const T&b){return b<a?(a=b,true):false;}
typedef long long ll;
typedef pair<int, int> pii;#ifndef ONLINE_JUDGE#include "local.h"
#endifconst int N = 1e4 + 7;
const int M = N;
const int inf = 1e9 + 7;namespace Edge {int last[N], to[M << 1], w[M << 1], next[M << 1], cntE;void init() {cntE = 0;memset(last, -1, sizeof(last));}void addEdge(int u, int v, int w) {to[cntE] = v;Edge::w[cntE] = w;next[cntE] = last[u];last[u] = cntE ++;}
}int n, K;namespace Center {int root, siz, son[N];void init() {siz = inf;}void getRoot(int cur, int fa, int total, bool used[]) {son[cur] = 0;int buf = 0;for (int i = Edge::last[cur]; ~i; i = Edge::next[i]) {int to = Edge::to[i];if (to != fa && !used[to]) {getRoot(to, cur, total, used);son[cur] += son[to] + 1;buf = max(buf, son[to] + 1);}}buf = max(buf, total - son[cur] - 1);if (buf < siz || buf == siz && cur < siz) {siz = buf;root = cur;}}
}void getDepth(int cur, int fa, int sum, vector<int> &vt, bool used[]) {vt.pb(sum);for (int i = Edge::last[cur]; ~i; i = Edge::next[i]) {int to = Edge::to[i], w = Edge::w[i];if (to != fa && !used[to]) getDepth(to, cur, sum + w, vt, used);}
}int getAns(vector<int> &vt) {sort(all(vt));int maxp = vt.size() - 1, ans = 0;for (int i = 0; i < maxp; i ++) {while (i < maxp && vt[i] + vt[maxp] > K) maxp --;ans += maxp - i;}return ans;
}bool used[N];int work(int cur) {used[cur] = true;vector<int> total;total.push_back(0);int ans = 0;for (int i = Edge::last[cur]; ~i; i = Edge::next[i]) {int to = Edge::to[i], w = Edge::w[i];if (!used[to]) {vector<int> local;getDepth(to, cur, w, local, used);ans -= getAns(local);for (int j = 0; j < local.size(); j ++) {total.push_back(local[j]);}Center::init();Center::getRoot(to, cur, local.size(), used);ans += work(Center::root);}}return ans += getAns(total);
}int main() {
#ifndef ONLINE_JUDGEfreopen("in.txt", "r", stdin);//freopen("out.txt", "w", stdout);
#endif // ONLINE_JUDGEwhile (cin >> n >> K, n || K) {int u, v, w;Edge::init();Center::init();mset(used, 0);for (int i = 1; i < n; i ++) {scanf("%d%d%d", &u, &v, &w);Edge::addEdge(u, v, w);Edge::addEdge(v, u, w);}Center::getRoot(1, 0, n, used);cout << work(Center::root) << endl;}return 0;
}

  

转载于:https://www.cnblogs.com/jklongint/p/4960052.html

[poj1741 Tree]树上点分治相关推荐

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

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

  2. POJ1741 Tree(点分治)

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

  3. POJ1741 Tree(树分治)

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

  4. BZOJ 3221: [Codechef FEB13] Obserbing the tree树上询问( 可持久化线段树 + 树链剖分 )

    树链剖分+可持久化线段树....这个一眼可以看出来, 因为可持久化所以写了标记永久化(否则就是区间修改的线段树的持久化..不会), 结果就写挂了, T得飞起...和管理员拿数据调后才发现= = 做法: ...

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

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

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

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

  7. poj1741 Tree 点分治

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

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

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

  9. [dsu on tree]树上启发式合并总结(算法思想及模板附例题练习)

    文章目录 前言 树上启发式合并 引入 算法思想 时间复杂度 模板 练习 例题:CF600E Lomsat gelral solution code CF208E Blood Cousins solut ...

最新文章

  1. SHELL基础学习必杀技之十三问
  2. GridView里面的HyperLink和ButtonField操作总结
  3. 海南橡胶机器人成本_完成专利授权20余件!海南橡胶中橡科技搭建高标准研发平台...
  4. mac os 开启redis_关于Redis,学会这8点就够了
  5. 怎么在pptv里下载电视剧
  6. 智慧中国杯算法赛解读 | 精准资助数据探索(一)
  7. 算法----字符串拷贝
  8. 找mysql软件的配置文件_mysql 查看当前使用的配置文件my.cnf的方法
  9. SpringMVC的拦截器(Interceptor)和过滤器(Filter)的区别与联系
  10. visio2019怎么对图片加箭头标注,Visio设置图片作为背景
  11. mysql数据库定时清理数据
  12. php.exe不是 32位有效应用程序,XP系统打开程序时提示“不是有效的Win32应用程序”怎么办?...
  13. mysql1682错误_ERROR 1682 (HY000)
  14. windows粘贴不了
  15. 店开天下,阿里云助力客如云数据中台建设
  16. 我他妈的怎么成了酷抠族!
  17. strstr函数的自己实现
  18. The JAVA_HOME environment variable is not defined correctly This environment variable is needed to r
  19. 新海诚没有参与制作的作品_由新海诚创作,却成为冷门的一部动漫,至今都没看懂...
  20. JavaScript快速入门到高级 JS精品视频课程

热门文章

  1. play home tifa_144Hz OLED屏手机 努比亚Play喜提Android 11_手机通讯
  2. 生新技能树单细胞GBM数据分析(SignleR以及Seurat 联合分析及细胞簇注释
  3. 辅助驾驶等级_BBA霸榜、特斯拉折戟 E-NCAP辅助驾驶评测结果公布
  4. 王益:分布式机器学习的故事
  5. 理清网站数据分析思路导图
  6. python3怎么安装mysql_Python3.7安装mysqlclient
  7. 系统学习深度学习(九)--激活函数总结
  8. C语言:采用交互式方式打开指定的文件,若文件打开成功,则显示该文件的大小,并显示文件内容,若文件打开失败,则提示出错信息
  9. linux文件描述符、软硬连接、输入输出重定向
  10. 了解一个新技术和技术点的时候需要了解的事情