POJ 1741 Tree【Tree,点分治】
树上的算法真的很有意思……哈哈。
给一棵边带权树,问两点之间的距离小于等于K的点对有多少个。
将无根树转化成有根树进行观察。满足条件的点对有两种情况:两个点的路径横跨树根,两个点位于同一颗子树中。
如果我们已经知道了此时所有点到根的距离a[i],a[x] + a[y] <= k的(x, y)对数就是结果,这个可以通过排序之后O(n)的复杂度求出。然后根据分治的思想,分别对所有的儿子求一遍即可,但是这会出现重复的——当前情况下两个点位于一颗子树中,那么应该将其减掉(显然这两个点是满足题意的,为什么减掉呢?因为在对子树进行求解的时候,会重新计算)。
在进行分治时,为了避免树退化成一条链而导致时间复杂度变为O(N^2),每次都找树的重心,这样,所有的子树规模就会变的很小了。时间复杂度O(Nlog^2N)。
树的重心的算法可以线性求解。
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
using namespace std;
#define N 10009
struct node {
int v, l;
node() {};
node(int _v, int _l): v(_v), l(_l) {};
};
vector<node> g[N];
int n, k, size, s[N], f[N], root, d[N], K, ans;
vector<int> dep;
bool done[N];
void getroot(int now, int fa) {
int u;
s[now] = 1; f[now] = 0;
for (int i=0; i<g[now].size(); i++)
if ((u = g[now][i].v) != fa && !done[u]) {
getroot(u, now);
s[now] += s[u];
f[now] = max(f[now], s[u]);
}
f[now] = max(f[now], size-s[now]);
if (f[now] < f[root]) root = now;
}
void getdep(int now, int fa) {
int u;
dep.push_back(d[now]);
s[now] = 1;
for (int i=0; i<g[now].size(); i++)
if ((u = g[now][i].v) != fa && !done[u]) {
d[u] = d[now] + g[now][i].l;
getdep(u, now);
s[now] += s[u];
}
}
int calc(int now, int init) {
dep.clear(); d[now] = init;
getdep(now, 0);
sort(dep.begin(), dep.end());
int ret = 0;
for (int l=0, r=dep.size()-1; l<r; )
if (dep[l] + dep[r] <= K) ret += r-l++;
else r--;
return ret;
}
void work(int now) {
int u;
ans += calc(now, 0);
done[now] = true;
for (int i=0; i<g[now].size(); i++)
if (!done[u = g[now][i].v]) {
ans -= calc(u, g[now][i].l);
f[0] = size = s[u];
getroot(u, root=0);
work(root);
}
}
int main() { while (scanf("%d%d", &n, &K) == 2) {
if (n == 0 && K == 0) break;
for (int i=0; i<=n; i++) g[i].clear();
memset(done, false, sizeof(done)); int u, v, l;
for (int i=1; i<n; i++) {
scanf("%d%d%d", &u, &v, &l);
g[u].push_back(node(v, l));
g[v].push_back(node(u, l));
}
f[0] = size = n;
getroot(1, root=0);
ans = 0;
work(root);
printf("%d\n", ans);
}
return 0;
}
POJ 1741 Tree【Tree,点分治】的更多相关文章
- poj 1741 树的点分治(入门)
Tree Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 18205 Accepted: 5951 Description ...
- 【POJ 1741】 Tree (树的点分治)
Tree Description Give a tree with n vertices,each edge has a length(positive integer less than 100 ...
- POJ 1741:Tree(树上点分治)
题目链接 题意 给一棵边带权树,问两点之间的距离小于等于K的点对有多少个. 思路 <分治算法在树的路径问题中的应用> 图片转载于http://www.cnblogs.com/Paul-Gu ...
- 【POJ 1741】Tree
Tree Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 11570 Accepted: 3626 Description ...
- 「POJ 1741」Tree
题面: Tree Give a tree with n vertices,each edge has a length(positive integer less than 1001). Define ...
- 【POJ 1741】 Tree
[题目链接] http://poj.org/problem?id=1741 [算法] 点分治 要求距离不超过k的点对个数,不妨将路径分成两类 : 1. 经过根节点 2. 不经过根节点 考虑第1类路径, ...
- POJ 1741 树的点分治
题目大意: 树上找到有多少条路径的边权值和>=k 这里在树上进行点分治,需要找到重心保证自己的不会出现过于长的链来降低复杂度 #include <cstdio> #include & ...
- POJ 1741 树上的点分治
题目大意: 找到树上点对间距离不大于K的点对数 这是一道简单的练习点分治的题,注意的是为了防止点分治时出现最后分治出来一颗子树为一条直线,所以用递归的方法求出最合适的root点 #include &l ...
- POJ 1741 树上 点的 分治
题意就是求树上距离小于等于K的点对有多少个 n2的算法肯定不行,因为1W个点 这就需要分治.可以看09年漆子超的论文 本题用到的是关于点的分治. 一个重要的问题是,为了防止退化,所以每次都要找到树的重 ...
- poj 1741 Tree(树的点分治)
poj 1741 Tree(树的点分治) 给出一个n个结点的树和一个整数k,问有多少个距离不超过k的点对. 首先对于一个树中的点对,要么经过根结点,要么不经过.所以我们可以把经过根节点的符合点对统计出 ...
随机推荐
- html文件引入其它html文件的几种方法:include方式
可以在一个html的文件当中读取另一个html文件的内容吗?答案是确定的,而且方法不只一种,在以前我只会使用iframe来引用,后来发现了另外的几种方法,那今天就总结这几种方法让大家参考一下. 1.I ...
- 原生javascript实现老.虎机抽奖点名demo源码思路解析
想着使用原生Javascript做一个随机点名的小应用, 也可以做抽奖使用. html简单化,人名单可以通过js生成并处理. 可以非常随意的添加修改人名字. 应用想带点特效,比如老.虎机转动的特效. ...
- hive premanent udf 发布...
起因: hive premanent udf 发布成功,但是hue 无法加载使用(但是cli 是可用的) ,处理半天,依然不可用!后来发现重启hiveserver2 就可以了 具体步骤如下: ...
- xcode6编译cocos2dx项目出现Undefined symbols _fwrite$UNIX2003
当xcode6编译cocos2dx的时候会出现Undefined symbols _fwrite$UNIX2003 这个问题.google了一篇文章:http://stackoverflow.com/ ...
- 整理一些常用函数库PHP版本
function msubstr($str, $start=0, $length, $charset="utf-8", $suffix=true) { if(function_ex ...
- 织梦dedecms|文章页通用标签
当前位置: {dede:field name='position'/}上一页: {dede:prenext get='pre'/}下一页: {dede:prenext get='next'/}收 ...
- C# 读书笔记之访问虚方法、重写方法和隐藏方法
C#允许派生类中的方法与基类中方法具有相同的签名:基类中使用关键字virtual定义虚方法:然后派生类中使用关键字override来重写方法,或使用关键字new来覆盖方法(隐藏方法). 重写方法用相同 ...
- TortoiseSVN是windows平台下Subversion的免费开源客户端。
一般我们都是先讲讲服务器的配置,然后再讲客户端的使用,但是在TortoiseSVN上,却可以反过来.因为,如果你的要求不高,只是想在本机,或者是可信任的局域网络中使用SVN版本控制,可以不需要安装SV ...
- MySQL DBA成长之路
http://blog.51cto.com/zt/579 :GRANT ALL PRIVILEGES ON *.* TO 'myuser'@'192.168.1.3' IDENTIFIED BY 'm ...
- 网站流量统计系统 phpMyVisites
phpMyVisites是一个网站流量统计系统,它能够提供非常详细的统计报告和高级图形报表.phpMyVisites不是一个Apache log分析工具,它建有自己的log.它的特点包括: 安装部署: ...