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的点对. 首先对于一个树中的点对,要么经过根结点,要么不经过.所以我们可以把经过根节点的符合点对统计出 ...
随机推荐
- 2.Freshman阶段学习内容的确定
我刷知乎.在知乎上答题的程序员,不是很牛逼就是更牛逼,说起各种系统.各种系统的各种版本.各种语言.数据库.算法.IT届的各种圣战都有板有眼.信手拈来.头头是道,不得不服.这导致了一些非常严重的问题:我 ...
- 图片变灰css3
-webkit-filter: grayscale(100%); -moz-filter: grayscale(100%); -ms-filter: grayscale(100%); -o-filte ...
- Javascript 递归函数
递归函数就是在函数内部调用它自己.在Javascript 中有很多写法,值得我们学习一下(Javascript太灵活了).还是用n的 阶乘 来写例子吧. 1. 首先,来看一个最普通 最正常的写法. f ...
- UltraISO做U盘启动盘教程
用UltraISO做U盘启动盘教程 注意:制作前请先备份u盘内重要文件 vista.win7系统需要以管理员身份运行UltraISO,其他系统直接运行即可 1.打开UltraISO选择iso镜像文件 ...
- POJ 1840 Brainman(逆序对数)
题目链接:http://poj.org/problem?id=1804 题意:给定一个序列a[],每次只允许交换相邻两个数,最少要交换多少次才能把它变成非递降序列. 思路:题目就是要求逆序对数,我们知 ...
- Hibernate的搭建及使用
1.创建普通的java项目. 因为Hibernate是一个轻量级的框架,不像servlet,还必须需要tomcat的支持,Hibernate只要jdk支持即可. 2.引入jar包. 可以在项目中直接引 ...
- tmod命令
tmod ./tpl --debug --no-watch --output ./tplbuild
- python列表元组
python列表元组 索引 切片 追加 删除 长度 循环 包含 定义一个列表 my_list = [] my_list = list() my_list = ['Michael', ' ...
- 自定义Chrome 背景色 (FF需要User Styles插件)
Chrome有个自定义背景色的文件 Custom.css 默认里面什么字都没写 html, body {background-color: #e0dcc0!important;} 这个颜色 ...
- 滚动条QScroolBar实现滚屏功能(屏幕过大,覆盖wheelEvent来处理滑轮事件)
环境:Qt5 编译器:Qt Creator 需求:如图 显示区域win 600*300 需要显示的Widget控件show 590*550 则有600*250的show界面无法显示 使用滑块控制sho ...