POJ 1741 Tree(树的点分治)
题目链接:http://poj.org/problem?id=1741
题意:给出一棵树,定义dis(u,v)为两个节点之间的距离。dis(u,v)<=K时成(u,v)是合法的。问有多少个合法的顶点对(u,v)?
思路:(1)树的重心:删掉树的一个顶点,树将分成若干个子树。若有一个顶点,删掉后,使得子树节点的最大值最小,则该点称为重心。
(2)树的点分治:不知道标准的定义。我的理解就是找到一个点,删掉,然后递归的处理各个子树。这就是树的点分治的思想。
(3)对于本题,每次找到当前树的重心作为根节点。首先我们计算出通过根节点的合法顶点对个数,然后递归处理子树即可。首先,求出每个点到根节点的距离。然后将所有距离排序,则可以利用单调性O(n)计算出合法的顶点对。如下:
sort(V1.begin(),V1.end());
int L=0,R=SZ(V1)-1;
while(L<R)
{
if(V1[L]+V1[R]<=m) ans+=R-L,L++;
else R--;
}
此时,有一些可能是只通过某个子树内的,因此还要先将其减去。
int n,m,ans;
vector<pair<int,int> > g[N];
int D[N],visit[N];
int s[N],Max[N];
vector<int> V1,V2;
int tot;
void DFS(int u,int pre)
{
s[u]=1; Max[u]=0; tot++;
int i,v;
FOR0(i,SZ(g[u]))
{
v=g[u][i].first;
if(v==pre||visit[v]) continue;
DFS(v,u);
s[u]+=s[v];
if(s[v]>Max[u]) Max[u]=s[v];
}
V1.pb(Max[u]); V2.pb(u);
}
int getRoot(int u)
{
V1.clear(); V2.clear(); tot=0;
DFS(u,-1);
int Min=INF,ans,i,temp;
FOR0(i,SZ(V1))
{
temp=max(V1[i],tot-V1[i]);
if(temp<Min) Min=temp,ans=V2[i];
}
return ans;
}
void getDeep(int u,int len,int pre)
{
V1.pb(len);
int i,v,w;
FOR0(i,SZ(g[u]))
{
v=g[u][i].first;
w=g[u][i].second;
if(v==pre||visit[v]) continue;
getDeep(v,len+w,u);
}
}
void solve(int u)
{
int root=getRoot(u);
V1.clear();
getDeep(root,0,-1);
sort(V1.begin(),V1.end());
int L=0,R=SZ(V1)-1;
while(L<R)
{
if(V1[L]+V1[R]<=m) ans+=R-L,L++;
else R--;
}
visit[root]=1;
int i,v,w;
FOR0(i,SZ(g[root]))
{
v=g[root][i].first;
w=g[root][i].second;
if(visit[v]) continue;
V1.clear(); getDeep(v,w,root);
sort(V1.begin(),V1.end());
L=0,R=SZ(V1)-1;
while(L<R)
{
if(V1[L]+V1[R]<=m) ans-=R-L,L++;
else R--;
}
}
FOR0(i,SZ(g[root]))
{
v=g[root][i].first;
if(!visit[v]) solve(v);
}
}
int main()
{
Rush(n)
{
RD(m);
if(!n&&!m) break;
int i;
FOR1(i,n) g[i].clear();
clr(visit,0);
int x,y,z;
FOR1(i,n-1)
{
RD(x,y,z);
g[x].pb(MP(y,z));
g[y].pb(MP(x,z));
}
ans=0; solve(1); PR(ans);
}
}
POJ 1741 Tree(树的点分治)相关推荐
- POJ 1741 Tree 树分治
题意: 给出一颗有\(n (n \leq 10^4)\)个节点的树,和一个\(k\).统计有多少个点对\(u, \, v(u \neq v)\)满足\(u\)到\(v\)的最短距离不超过\(k\). ...
- POJ 1741 Tree(树分治)
去网上搜题解大多数都是说论文,搜了论文看了看,写的确实挺好,直接复制过来. 不过代码中有些细节还是要注意的,参考这篇http://blog.sina.com.cn/s/blog_6d5aa19a010 ...
- [POJ 1741] Tree
Link: POJ 1741 传送门 Solution: 此题的难点在于点分治上的统计 如果依然采取每棵子树的结果与之前所有子树的结果合并的方式会比较麻烦 同时复杂度可能超过$O(n*log(n))$ ...
- POJ 1741 Tree(点分治)
题意 一棵 \(n\) 个节点的树,求两点间距离不超过 \(k\) 的点对对数. 思路 点分治模板题,点分治一般用来解决树上的路径问题,核心在于找出重心,算经过重心的合法路径,然后以重心把树劈成若干个 ...
- POJ - 1741 Tree(点分治模板题)
题目链接:点击查看 题目大意:给出一棵 n 个节点的树,现在定义 dis( x , y ) 为点 x 和点 y 之间的路径长度,现在问 dis ( x , y ) <= k 的点对有多少 题目分 ...
- POJ 3237.Tree -树链剖分(边权)(边值更新、路径边权最值、区间标记)贴个板子备忘...
Tree Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 12247 Accepted: 3151 Descriptio ...
- POJ 3237 Tree (树链剖分 路径剖分 线段树的lazy标记)
题目链接:http://poj.org/problem?id=3237 一棵有边权的树,有3种操作. 树链剖分+线段树lazy标记.lazy为0表示没更新区间或者区间更新了2的倍数次,1表示为更新,每 ...
- poj 1741 Tree
点分治裸题23333这个题如果K很大的话就不能用依次处理每棵子树做了.(数组存不开2333) 这个就只能是总的依次减去每棵子树里的. 1 #include<cstdio> 2 #inclu ...
- 【CF 600E】Lomsat gelral(树上启发式合并, dsu on tree, 静态链分治,模板题)
Algorithm 名称:树上启发式合并, dsu on tree, 静态链分治 用处:一般用来解决一类不带修改的子树查询问题 核心思想为:利用重链剖分的性质优化子树贡献的计算. 前置知识:启发式合并 ...
最新文章
- Ansible批量添加远程登录用户
- 【iOS基础知识】const与宏的区别
- B10_NumPy数组操作、修改数组形状、翻转数组、修改数组维度、连接数组、分割数组、数组元素的添加与删除
- php队列会停止执行吗,php – Laravel Artisan CLI安全地停止守护程序队列工作者
- linux C 基于链表链的定时器
- vsftpd FTP Server ‘ls.c‘ 远程拒绝服务漏洞(CVE-2011-0762)漏洞修复方案
- javafor循环打印图案_C程序使用循环打印盒子图案
- 【git】git提交忽略不必要的文件或文件夹
- 真实VS虚拟,虚拟现实如何定义
- Asp.net 中 IHttpHandlerFactory接口 对应web.config 中的节点
- scrum角色及其职责介绍
- Axure RP 9 下载、汉化及最新授权码
- 从苏宁电器到卡巴斯基(后传)第04篇:还愿吾爱破解视频教程大赛
- oracle ^]字符,oracle 字符串操作
- 鲁四海解读中国大数据发展10大趋势5大挑战 —— 首席数据官联盟2016《中国大数据企业排行榜》发布会实录...
- 怎么让termux运行Java_在安卓手机上通过 Termux 运行编译/运行 .NET 应用
- 企业微信号发消息给指定成员
- dz程序上传服务器的位置,dz手机端上传到远程服务器
- 表空间管理——创建TABLESPACE
- 深度学习模型评价标准