【poj1741】Tree 树的点分治
题目描述
Define dist(u,v)=The min distance between node u and v.
Give an integer k,for every pair (u,v) of vertices is called valid if and only if dist(u,v) not exceed k.
Write a program that will count how many pairs which are valid for a given tree.
输入
The last test case is followed by two zeros.
输出
样例输入
5 4
1 2 3
1 3 1
1 4 2
3 5 1
0 0
样例输出
8
题目大意
多组测试数据,每次输入n、m,和一棵n个点的有边权的树,问你满足x到y距离小于等于m的无序点对(x,y)的个数是多少。
题解
树的点分治模板题,第一次写
考虑到路径只有两种情况,一是经过根节点,二是不经过根节点。
如果不经过根节点,那么一定经过最小公共子树的根节点,可以转化为问题一的子问题。
于是考虑怎么递归解决问题一。
对于根节点进行一次dfs,求出deep,并将其从小到大排序。
避免重复,只需要求出其中deep[x]≤deep[y]且deep[x]+deep[y]≤m的个数。
用i表示左指针,j表示右指针,i从左向右遍历。
如果deep[i]+deep[j]≤m,则点对(i,t)(i<t≤j)都符合题意,将j-i加入答案中,并且i++;否则j--。
然而这样还会重复计算在同一棵子树中的点对,所以再进行下一步dfs之前需要减去重复部分。
但是这样做会TLE。为什么?因为树可能会退化,导致选择链头时时间复杂度极大。
于是每次不能固定选择root,而是以重心作为root去处理,这样能保证时间复杂度再O(nlog2n)以下。
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 10010
using namespace std;
int m , head[N] , to[N << 1] , len[N << 1] , next[N << 1] , cnt , si[N] , deep[N] , root , vis[N] , f[N] , sn , d[N] , tot , ans;
void add(int x , int y , int z)
{
to[++cnt] = y , len[cnt] = z , next[cnt] = head[x] , head[x] = cnt;
}
void getroot(int x , int fa)
{
f[x] = 0 , si[x] = 1;
int i;
for(i = head[x] ; i ; i = next[i])
if(to[i] != fa && !vis[to[i]])
getroot(to[i] , x) , si[x] += si[to[i]] , f[x] = max(f[x] , si[to[i]]);
f[x] = max(f[x] , sn - si[x]);
if(f[root] > f[x]) root = x;
}
void getdeep(int x , int fa)
{
d[++tot] = deep[x];
int i;
for(i = head[x] ; i ; i = next[i])
if(to[i] != fa && !vis[to[i]])
deep[to[i]] = deep[x] + len[i] , getdeep(to[i] , x);
}
int calc(int x)
{
tot = 0 , getdeep(x , 0) , sort(d + 1 , d + tot + 1);
int i = 1 , j = tot , sum = 0;
while(i < j)
{
if(d[i] + d[j] <= m) sum += j - i , i ++ ;
else j -- ;
}
return sum;
}
void dfs(int x)
{
deep[x] = 0 , vis[x] = 1 , ans += calc(x);
int i;
for(i = head[x] ; i ; i = next[i])
if(!vis[to[i]])
deep[to[i]] = len[i] , ans -= calc(to[i]) , sn = si[to[i]] , root = 0 , getroot(to[i] , 0) , dfs(root);
}
int main()
{
int n , i , x , y , z;
while(scanf("%d%d" , &n , &m) && (n || m))
{
memset(head , 0 , sizeof(head));
memset(vis , 0 , sizeof(vis));
cnt = 0 , ans = 0;
for(i = 1 ; i < n ; i ++ )
scanf("%d%d%d" , &x , &y , &z) , add(x , y , z) , add(y , x , z);
f[0] = 0x7fffffff , sn = n;
root = 0 , getroot(1 , 0) , dfs(root);
printf("%d\n" , ans);
}
return 0;
}
【poj1741】Tree 树的点分治的更多相关文章
- POJ1741——Tree(树的点分治)
1 /* *********************************************** 2 Author :kuangbin 3 Created Time :2013-11-17 1 ...
- hdu 4812 D Tree(树的点分治)
D Tree Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 102400/102400 K (Java/Others) Total ...
- [poj1741][tree] (树/点分治)
Description Give a tree with n vertices,each edge has a length(positive integer less than 1001). Def ...
- POJ1741 Tree 树分治模板
http://poj.org/problem?id=1741 题意:一棵n个点的树,每条边有距离v,求该树中距离小于等于k的点的对数. dis[y]表示点y到根x的距离,v代表根到子树根的距离 ...
- POJ1741(SummerTrainingDay08-G 树的点分治)
Tree Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 23380 Accepted: 7748 Description ...
- hdu4812-D Tree (树的点分治)
昨天学了下树分治,今天补这道题,还是太不熟练了,写完之后一直超时.后来查出好多错= =比如v,u写倒了,比如+写成了取最值,比如....爆int...查了两个多小时的错..哭...(没想到进首页了 h ...
- 【POJ 1741】 Tree (树的点分治)
Tree Description Give a tree with n vertices,each edge has a length(positive integer less than 100 ...
- 树上点对统计poj1741(树的点分治)
给定一棵树,边上有权值,要统计有多少对点路径的权值和<=k 分治算法在树的路径中的应用 这个论文里面有分析. 任意两点的路径,要么过根结点,要么在子树中.如果在子树中,那么只要递归处理就行了. ...
- POJ 1741 Tree(树的点分治,入门题)
Tree Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 21357 Accepted: 7006 Description ...
随机推荐
- ElasticSearch启动错误处理方法
在配置完elasticsearch,启动程序会包如下错误: [elk@localhost bin]$ ./elasticsearch ... ... ERROR: [3] bootstrap chec ...
- MySQL命令,一篇文章替你全部搞定
MySQL命令,一篇文章替你全部搞定 MySQL的基本操作可以包括两个方面:MySQL常用语句如高频率使用的增删改查(CRUD)语句和MySQL高级功能,如存储过程,触发器,事务处理等.而这两个方面又 ...
- PHP中防止SQL注入
防止SQL注入,我们需要注意以下几个要点: 1.永远不要信任用户的输入.对用户的输入进行校验,可以通过正则表达式,或限制长度:对单引号和 双"-"进行转换等. 2.永远不要使用动态 ...
- 怎么自行HTTP的POST包头,需要使用json
http://bbs.csdn.net/topics/390674431 不理解你为什么这么传 post的格式如下:POST / HTTP/1.1Host: www.wrox.comUser-Agen ...
- python 二维数组读入
study from : https://www.cnblogs.com/reaptomorrow-flydream/p/9613847.html python 二维数组键盘输入 1 m = int( ...
- 斯坦福大学公开课机器学习: advice for applying machine learning | regularization and bais/variance(机器学习中方差和偏差如何相互影响、以及和算法的正则化之间的相互关系)
算法正则化可以有效地防止过拟合, 但正则化跟算法的偏差和方差又有什么关系呢?下面主要讨论一下方差和偏差两者之间是如何相互影响的.以及和算法的正则化之间的相互关系 假如我们要对高阶的多项式进行拟合,为了 ...
- 第十四节,卷积神经网络之经典网络Inception(四)
一 1x1卷积 在架构内容设计方面,其中一个比较有帮助的想法是使用 1×1 卷积.也许你会好奇,1×1 的卷积能做什么呢?不就是乘以数字么?听上去挺好笑的,结果并非如此,我们来具体看看. 过滤器为 1 ...
- Day30--Python--struct, socketserver
1. struct struct.pack 打包 def pack(fmt, *args): # known case of _struct.pack """ pack( ...
- Mock3 moco框架的http协议post方法Mock的实现
新建一个 startupPost.json [ { "description":"模拟一个post请求", "request":{ &quo ...
- TestNg 5.类分组
类分组是可以给类去分组,几个类分成不同的组. 比如,建立3个类GroupsOnClass1,GroupsOnClass2,GroupsOnClass3. GroupsOnClass1和Groups ...