点分治【bzoj1468】 Tree

Description

给你一棵TREE,以及这棵树上边的距离.问有多少对点它们两者间的距离小于等于K

Input

N(n<=40000) 接下来n-1行边描述管道,按照题目中写的输入 接下来是k

Output

一行,有多少对点之间的距离小于等于k

点分治开始入门。

点分治,主要是解决形如:给你一棵树,求树上满足XX条件的点对的对数。

所以说应对的问题很多时候都和树形DP相同。

首先告诉自己,分治是高效的算法。

想一下,平时在面对普通的分治问题,每次肯定都是半分,直到成为小问题,然后再分别解决。

为了保证点分治的高效,所以我们每一次应该将当前问题分成最平均的两个问题,放到树上就是指我们要将当前的树分成大小最平均的几棵。

那么就可以引入一个概念:树的重心。定义是在树上找一个点作为根,使得子树中的size最大者最小,这样我们就可以很好的将树平均分。

所以解决点分治问题的基本思路也就有了:

​ 我们从整棵树开始,每一次找到当前树的重心并且以他为根,也就是将无根树转成有根树,然后对于当前的树,我们只对与当前树的根的点对进行处理。

​ 对于这道题来说,就是找到路径经过当前根的点对,去统计这些点对中符合条件的数量对答案作出贡献。

​ 然后对于每个子树,向下分治,继续找重心……

另外,和【bzoj3365】是一样的题。

code

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<algorithm>
  4. using namespace std;
  5. const int wx=40017;
  6. inline int read(){
  7. int sum=0,f=1;char ch=getchar();
  8. while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
  9. while(ch>='0'&&ch<='9'){sum=(sum<<1)+(sum<<3)+ch-'0';ch=getchar();}
  10. return sum*f;
  11. }
  12. int n,m,ans,num,root,k,tmp;
  13. int head[wx],dis[wx],size[wx];
  14. int f[wx],vis[wx];
  15. int temp[wx];
  16. struct e{
  17. int nxt,to,dis;
  18. }edge[wx*2];
  19. void add(int from,int to,int dis){
  20. edge[++num].nxt=head[from];
  21. edge[num].to=to;
  22. edge[num].dis=dis;
  23. head[from]=num;
  24. }
  25. void getroot(int u,int fa){
  26. size[u]=1;f[u]=0;
  27. for(int i=head[u];i;i=edge[i].nxt){
  28. int v=edge[i].to;
  29. if(v==fa||vis[v])continue;
  30. getroot(v,u);
  31. size[u]+=size[v];
  32. f[u]=max(f[u],size[v]);
  33. }
  34. f[u]=max(f[u],tmp-size[u]);
  35. if(f[root]>f[u])root=u;
  36. }
  37. void dfs(int u,int fa){
  38. temp[++temp[0]]=dis[u];
  39. for(int i=head[u];i;i=edge[i].nxt){
  40. int v=edge[i].to;
  41. if(v==fa||vis[v])continue;
  42. dis[v]=dis[u]+edge[i].dis;
  43. dfs(v,u);
  44. }
  45. }
  46. int calc(int u,int now){
  47. dis[u]=now;temp[0]=0;dfs(u,0);
  48. int l=1,r=temp[0];int re=0;
  49. sort(temp+1,temp+temp[0]+1);
  50. while(l<r){
  51. if(temp[r]+temp[l]<=k)re+=r-l,l++;
  52. else r--;
  53. }
  54. return re;
  55. }
  56. void slove(int u){
  57. vis[u]=1;ans+=calc(u,0);
  58. for(int i=head[u];i;i=edge[i].nxt){
  59. int v=edge[i].to;
  60. if(vis[v])continue;
  61. ans-=calc(v,edge[i].dis);
  62. root=0;tmp=size[v];getroot(v,0);slove(root);
  63. }
  64. }
  65. int main(){
  66. n=read();
  67. for(int i=1;i<n;i++){
  68. int x,y,z;
  69. x=read();y=read();z=read();
  70. add(x,y,z);add(y,x,z);
  71. }
  72. k=read();
  73. f[0]=(1<<30);tmp=n;
  74. getroot(1,0);
  75. slove(root);
  76. printf("%d\n",ans);
  77. return 0;
  78. }

点分治【bzoj1468】 Tree的更多相关文章

  1. POJ1741 Tree + BZOJ1468 Tree 【点分治】

    POJ1741 Tree + BZOJ1468 Tree Description Give a tree with n vertices,each edge has a length(positive ...

  2. P4169-CDQ分治/K-D tree(三维偏序)-天使玩偶

    P4169-CDQ分治/K-D tree(三维偏序)-天使玩偶 这是一篇两种做法都有的题解 题外话 我写吐了-- 本着不看题解的原则,没写(不会)K-D tree,就写了个cdq分治的做法.下面是我的 ...

  3. BZOJ1468:Tree(点分治)

    Description 给你一棵TREE,以及这棵树上边的距离.问有多少对点它们两者间的距离小于等于K Input N(n<=40000) 接下来n-1行边描述管道,按照题目中写的输入 接下来是 ...

  4. 洛谷4178 BZOJ1468 Tree题解点分治

    点分治的入门练习. 题目链接 BZOJ的链接(权限题) 关于点分治的思想我就不再重复了,这里重点说一下如何判重. 我们来看上图,假设我们去除了1节点,求出d[2]=1,d[3]=d[4]=2 假设k为 ...

  5. 【点分治】bzoj1468 Tree

    同poj1741. 换了个更快的姿势,不会重复统计然后再减掉什么的啦~ #include<cstdio> #include<algorithm> #include<cst ...

  6. bzoj1468 Tree

    最经典的点分治题目,在递归子树的时候减去在算父亲时的不合法方案. #include<iostream> #include<cstdio> #include<cstring ...

  7. POJ3714 Raid 分治/K-D Tree

    VJ传送门 简要题意:给出两个大小均为\(N\)的点集\(A,B\),试在\(A\)中选择一个点,在\(B\)中选择一个点,使得它们在所有可能的选择方案中欧几里得距离最小,求出这个距离 下面给出的两种 ...

  8. BZOJ1468: Tree & BZOJ3365: [Usaco2004 Feb]Distance Statistics 路程统计

    [传送门:BZOJ1468&BZOJ3365] 简要题意: 给出一棵n个点的树,和每条边的边权,求出有多少个点对的距离<=k 题解: 点分治模板题 点分治的主要步骤: 1.首先选取一个点 ...

  9. 【BZOJ-1468】Tree 树分治

    1468: Tree Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1025  Solved: 534[Submit][Status][Discuss] ...

随机推荐

  1. listen and translation exercise 49

    Huh? Appears to Be Universally Understood What's the most universal utterance in languages across th ...

  2. mysql绿色安装

    先下载需要的文件: MySQL5.1(绿色).rar 和 MySQL-Front_v5.3(绿色版).rar 都是绿色免安装版 1.解压MySQL Server 5.1.rar到MySQL Serve ...

  3. bzoj 4815 小Q的表格 —— 反演+分块

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4815 思路就和这里一样:https://blog.csdn.net/leolyun/arti ...

  4. java多线程编程核心技术——第四章总结

    第一节使用ReentrantLock类 1.1使用ReentrantLock实现同步:测试1 1.2使用ReentrantLock实现同步:测试2 1.3使用Condition实现等待/同步错误用法与 ...

  5. 机器学习:Jupyter Notebook中Matplotlib的使用

    一.matplotlib绘制折线图 matplotlib绘图的实质是折线图,将所有的点用直线连接起来,由于距离比较密,看起来像是个平滑的曲线: import matplotlib as mpl:加载m ...

  6. jquery 中post 、get的同步问题,从外部获取返回数据

    解决方法1: 在全局设置: $.ajaxSetup({ async : false }); $.ajaxSetup({ async : false }); 然后再使用post或get方法 $.get( ...

  7. AD9各种布线总结

    1.常规布线:不详细说了,是个人就知道怎么弄.需要说明的是在布线过程中,可按小键盘的*键或大键盘的数字2键添加一个过孔:按L键可以切换布线层:按数字3可设定最小线宽.典型线宽.最大线宽的值进行切换. ...

  8. VisualGDB系列2:VisualGDB对Linux平台的支持特性

    根据VisualGDB官网(https://visualgdb.com)的帮助文档大致翻译而成.主要是作为个人学习记录.有错误的地方,Robin欢迎大家指正. 1 复杂问题的直观解决方案 只需要轻点几 ...

  9. asp后端弹出框

    RegisterStartupScript("提示信息", "<script>alert('Hello')</script>"); 这样 ...

  10. C基础题-sizeof

    sizeof  C语言中判断数据类型或者表达式长度符:关键字:字节数的计算在程序编译时进行,而不是在程序执行的过程中才计算出来! 一.关于sizeof简单的总结 1.sizeof的使用形式:sizeo ...