poj 1741 树分治
2015-08-19 11:33
323 查看
题意:
求树上距离不超过k的点对数
解决:
很经典的树分治
先不考虑树退化的情况。
对每个节点u,假设u有x个子节点,v1 v2 v3 .. vx,求出以u为根的子树上,所有不属于同一个v节点的,且距离不大于k的点对数。
且递归下去就是答案,无重无缺。
至于如何求上述的点对数量,
假设A = 以u为根节点的子树上所有的距离不大于k的点对数
B = 以u为根节点的子树上,同时属于u的某个同一个子节点v的,且距离不大于k的点对数
则 A - B 即为答案
下面加上,考虑树退化的问题,每次在dfs的时候,找到当前u为根的子树的重心,作为根去处理即可。
View Code
求树上距离不超过k的点对数
解决:
很经典的树分治
先不考虑树退化的情况。
对每个节点u,假设u有x个子节点,v1 v2 v3 .. vx,求出以u为根的子树上,所有不属于同一个v节点的,且距离不大于k的点对数。
且递归下去就是答案,无重无缺。
至于如何求上述的点对数量,
假设A = 以u为根节点的子树上所有的距离不大于k的点对数
B = 以u为根节点的子树上,同时属于u的某个同一个子节点v的,且距离不大于k的点对数
则 A - B 即为答案
下面加上,考虑树退化的问题,每次在dfs的时候,找到当前u为根的子树的重心,作为根去处理即可。
#include <cstdio> #include <algorithm> #include <cstring> #include <vector> const int MAXN = 1e4+10; const int MAXM = MAXN<<2; struct Edge{ int u, v, w, next; Edge(int _u, int _v, int _w, int _next) { u = _u; v = _v; w = _w; next = _next; } Edge(){} }edge[MAXM]; int tot, head[MAXN]; int n, k; int siz[MAXN]; int max_sub[MAXN]; int dist[MAXN]; bool vis[MAXN]; int max_siz, root; std::vector<int> ve; int res; void inline addEdge(int u, int v, int w) { edge[++tot] = Edge(u, v, w, head[u]); head[u] = tot; } void init() { tot = 1; res = 0; memset(head, 0, sizeof head); memset(vis, false, sizeof vis); } void getRoot(int u, int fa_node, int root_now) { max_sub[u] = std::max(max_sub[u], siz[root_now] - siz[u]); if (max_siz > max_sub[u]) { max_siz = max_sub[u]; root = u; } for (int i = head[u]; i > 0; i = edge[i].next) { int v = edge[i].v; if (v == fa_node || true == vis[v]) continue; getRoot(v, u, root_now); } } void getSize(int u, int fa_node) { siz[u] = 1, max_sub[u] = 0; for (int i = head[u]; i > 0; i = edge[i].next) { int v = edge[i].v; if (v == fa_node || true == vis[v]) continue; getSize(v, u); siz[u] += siz[v]; max_sub[u] = std::max(max_sub[u], siz[v]); } } void getDist(int u, int fa_node, int d) { ve.push_back(d); for (int i = head[u]; i > 0; i = edge[i].next) { int v = edge[i].v, w = edge[i].w; if (v == fa_node || true == vis[v]) continue; getDist(v, u, d+w); } } int calc(int u, int d) { ve.clear(); getDist(u, -1, d); std::sort(ve.begin(), ve.end()); int ans = 0; int l = 0, r = ve.size() - 1; while (l <= r) { if (ve[l] + ve[r] <= k) { ans += (r - l); ++l; } else --r; } return ans; } void dfs(int u) { getSize(u, -1); max_siz = n; getRoot(u, -1, u); res += calc(root, 0); vis[root] = true; for (int i = head[root]; i > 0; i = edge[i].next) { int v = edge[i].v, w = edge[i].w; if (true == vis[v]) continue; res -= calc(v, w); dfs(v); } } int main() { while (~scanf("%d%d", &n, &k), (n||k)) { init(); for (int i = 1, u, v, w; i <= n-1; ++i) { scanf("%d%d%d", &u, &v, &w); addEdge(u, v, w); addEdge(v, u, w); } dfs(1); printf("%d\n", res); } }
View Code
相关文章推荐
- centos下把python版本升级成2.7
- 开发日记(7)如何让一个activity更新application中的数据,返回后更新呢?
- win10更新定点设置后电脑Fn键失灵该怎么办?
- HDU2602
- android浏览器插件介绍
- Spring+Hibernate 数据库配置信息的加密
- IOS UITableView拖动排序功能
- hibernate注解方式实现一对多映射
- 数组的练习
- 2015 HUAS Summer Trainning #6~O
- 【iOS学习】八、JSON数据学习
- JS实现仿新浪微博发布内容为空时提示功能代码
- ubuntu下安装 oracle客户端
- Leetcode -- Ugly Number II
- 项目运行:The Tomcat server configuration at \Servers\Tomcat v6.0 Server at localhost-config is missing.
- K3固定资产卡片新增提示“SetBlob数据类型不符 = 0
- 用批处理如何实现telnet登陆并进行一些简单命令
- 我在工作中遇到的JS问题汇总
- openwrt wifi 配置
- mysql修改definer方法