【传送门:BZOJ1468&BZOJ3365


简要题意:

  给出一棵n个点的树,和每条边的边权,求出有多少个点对的距离<=k


题解:

  点分治模板题

  点分治的主要步骤:

  1、首先选取一个点,把无根树变成有根树。 那么如何选点呢? ——树形DP

  因为树是递归定义的,所以我们当然希望递归的层数最小。 每次选取的点,要保证与此点相连的结点数最多的连通块的结点数最小,我们把这个点叫做“重心”

  那么找到一颗树的重心有以下算法:

  (1)dfs一次,算出以每个点为根的子树大小

  (2)记录以每个结点为根的最大子树的大小

  (3)判断:如果以当前结点为根的最大子树大小比当前根更优,更新当前根

  2、处理联通块中通过根结点的路径

  3、标记根结点(相当于处理过后,将根结点从子树中删除)

  4、递归处理以当前点的儿子为根的每棵子树


参考代码(一):

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<cstdlib>
  4. #include<cmath>
  5. #include<algorithm>
  6. using namespace std;
  7. struct node
  8. {
  9. int x,y,d,next;
  10. }a[];int len,last[];
  11. void ins(int x,int y,int d)
  12. {
  13. len++;
  14. a[len].x=x;a[len].y=y;a[len].d=d;
  15. a[len].next=last[x];last[x]=len;
  16. }
  17. int tot[],root,sum,ms[];
  18. bool v[];
  19. void getroot(int x,int fa)
  20. {
  21. tot[x]=;ms[x]=;
  22. for(int k=last[x];k;k=a[k].next)
  23. {
  24. int y=a[k].y;
  25. if(y!=fa&&v[y]==false)
  26. {
  27. getroot(y,x);
  28. tot[x]+=tot[y];
  29. ms[x]=max(ms[x],tot[y]);
  30. }
  31. }
  32. ms[x]=max(ms[x],sum-tot[x]);
  33. if(ms[root]>ms[x]) root=x;
  34. }
  35. int dep[],id;
  36. int dd[];
  37. void getdep(int x,int fa)
  38. {
  39. dep[++id]=dd[x];
  40. for(int k=last[x];k;k=a[k].next)
  41. {
  42. int y=a[k].y;
  43. if(y!=fa&&v[y]==false)
  44. {
  45. dd[y]=dd[x]+a[k].d;
  46. getdep(y,x);
  47. }
  48. }
  49. }
  50. int ans=;
  51. int k;
  52. int cal(int x,int d)
  53. {
  54. dd[x]=d;id=;
  55. getdep(x,);
  56. sort(dep+,dep+id+);
  57. int l=,r=id,c=;
  58. while(l<r)
  59. {
  60. if(dep[l]+dep[r]<=k){c+=r-l;l++;}
  61. else r--;
  62. }
  63. return c;
  64. }
  65. void solve(int x)
  66. {
  67. ans+=cal(x,);
  68. v[x]=true;
  69. for(int k=last[x];k;k=a[k].next)
  70. {
  71. int y=a[k].y;
  72. if(v[y]==false)
  73. {
  74. ans-=cal(y,a[k].d);
  75. sum=tot[y];
  76. root=;getroot(y,x);
  77. solve(root);
  78. }
  79. }
  80. }
  81. int main()
  82. {
  83. int n;
  84. scanf("%d",&n);
  85. len=;memset(last,,sizeof(last));
  86. for(int i=;i<n;i++)
  87. {
  88. int x,y,d;
  89. scanf("%d%d%d",&x,&y,&d);
  90. ins(x,y,d);ins(y,x,d);
  91. }
  92. scanf("%d",&k);
  93. memset(v,false,sizeof(v));
  94. ans=;
  95. sum=tot[]=n;
  96. ms[]=<<-;
  97. root=;getroot(,);
  98. solve(root);
  99. printf("%d\n",ans);
  100. return ;
  101. }

参考代码(二):

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<cstdlib>
  4. #include<cmath>
  5. #include<algorithm>
  6. using namespace std;
  7. struct node
  8. {
  9. int x,y,d,next;
  10. }a[];int len,last[];
  11. void ins(int x,int y,int d)
  12. {
  13. len++;
  14. a[len].x=x;a[len].y=y;a[len].d=d;
  15. a[len].next=last[x];last[x]=len;
  16. }
  17. int tot[],root,sum,ms[];
  18. bool v[];
  19. void getroot(int x,int fa)
  20. {
  21. tot[x]=;ms[x]=;
  22. for(int k=last[x];k;k=a[k].next)
  23. {
  24. int y=a[k].y;
  25. if(y!=fa&&v[y]==false)
  26. {
  27. getroot(y,x);
  28. tot[x]+=tot[y];
  29. ms[x]=max(ms[x],tot[y]);
  30. }
  31. }
  32. ms[x]=max(ms[x],sum-tot[x]);
  33. if(ms[root]>ms[x]) root=x;
  34. }
  35. int dep[],id;
  36. int dd[];
  37. void getdep(int x,int fa)
  38. {
  39. dep[++id]=dd[x];
  40. for(int k=last[x];k;k=a[k].next)
  41. {
  42. int y=a[k].y;
  43. if(y!=fa&&v[y]==false)
  44. {
  45. dd[y]=dd[x]+a[k].d;
  46. getdep(y,x);
  47. }
  48. }
  49. }
  50. int ans=;
  51. int k;
  52. int cal(int x,int d)
  53. {
  54. dd[x]=d;id=;
  55. getdep(x,);
  56. sort(dep+,dep+id+);
  57. int l=,r=id,c=;
  58. while(l<r)
  59. {
  60. if(dep[l]+dep[r]<=k){c+=r-l;l++;}
  61. else r--;
  62. }
  63. return c;
  64. }
  65. void solve(int x)
  66. {
  67. ans+=cal(x,);
  68. v[x]=true;
  69. for(int k=last[x];k;k=a[k].next)
  70. {
  71. int y=a[k].y;
  72. if(v[y]==false)
  73. {
  74. ans-=cal(y,a[k].d);
  75. sum=tot[y];
  76. root=;getroot(y,x);
  77. solve(root);
  78. }
  79. }
  80. }
  81. int main()
  82. {
  83. int n,m;
  84. scanf("%d%d",&n,&m);
  85. len=;memset(last,,sizeof(last));
  86. for(int i=;i<=m;i++)
  87. {
  88. int x,y,d;char st[];
  89. scanf("%d%d%d%s",&x,&y,&d,st+);
  90. ins(x,y,d);ins(y,x,d);
  91. }
  92. scanf("%d",&k);
  93. memset(v,false,sizeof(v));
  94. ans=;
  95. sum=tot[]=n;
  96. ms[]=<<-;
  97. root=;getroot(,);
  98. solve(root);
  99. printf("%d\n",ans);
  100. return ;
  101. }

BZOJ1468: Tree & BZOJ3365: [Usaco2004 Feb]Distance Statistics 路程统计的更多相关文章

  1. BZOJ_3365_[Usaco2004 Feb]Distance Statistics 路程统计&&POJ_1741_Tree_点分治

    BZOJ_3365_[Usaco2004 Feb]Distance Statistics 路程统计&&POJ_1741_Tree_点分治 Description     在得知了自己农 ...

  2. bzoj 3365 [Usaco2004 Feb]Distance Statistics 路程统计(点分治,单调)

    [题意] 求树上长度不超过k的点对数目. [思路] 和 Tree 一样一样的. 就是最后统计的时候别忘把根加上. [代码] #include<set> #include<cmath& ...

  3. 【刷题】BZOJ 3365 [Usaco2004 Feb]Distance Statistics 路程统计

    Description 在得知了自己农场的完整地图后(地图形式如前三题所述),约翰又有了新的问题.他提供 一个整数K(1≤K≤109),希望你输出有多少对农场之间的距离是不超过K的. Input 第1 ...

  4. BZOJ 3365: [Usaco2004 Feb]Distance Statistics 路程统计

    Description 一棵树,统计距离不大于 \(k\) 的点对个数. Sol 点分治. 发现自己快把点分治忘干净了... 找重心使所有儿子的最大值尽量小,然后每次处理全部子树,再减去每个子树的贡献 ...

  5. bzoj 3365: [Usaco2004 Feb]Distance Statistics 路程统计【容斥原理+点分治】

    统计在一个root下的两个子树,每个子树都和前面的运算一下再加进去对于这种需要排序的运算很麻烦,所以考虑先不去同子树内点对的算出合法点对个数,然后减去每一棵子树内的合法点对(它们实际上是不合法的,相当 ...

  6. BZOJ 3364: [Usaco2004 Feb]Distance Queries 距离咨询

    Description 一棵树,询问两点间距离. Sol 倍增. 方向没用. 没有然后了. Code /************************************************ ...

  7. 【点分治】poj1741 Tree / poj2114 Boatherds / poj1987 Distance Statistics

    三道题都很类似.给出1741的代码 #include<cstdio> #include<algorithm> #include<cstring> using nam ...

  8. LCA【bzoj3364】 [Usaco2004 Feb]Distance Queries 距离咨询

    Description  奶牛们拒绝跑马拉松,因为她们悠闲的生活无法承受约翰选择的如此长的赛道.因此约翰决心找一条更合理的赛道,他打算咨询你.此题的地图形式与前两题相同.但读入地图之后,会有K个问题. ...

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

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

随机推荐

  1. ArcEngine 一些实现代码

    转自原文 ArcEngine 一些实现代码     ●·● 目录: A1 …………实现:鼠标滑过显示要素 tip A2 …………实现:通过鼠标选择要素并高亮显示(ISelectionEnvironme ...

  2. n个骰子,和为x的概率分别是多少

    开始我居然又没有想出来.. 还是看了解法.开始的时候,一直想的是用概率,百分比来求,后来才发现,用次数来求,最后除一下,更近清晰. 方法,可以是递归,每次多一个骰子的时候,次数分别加上个数以及上一次i ...

  3. CSS3可伸缩框属性,可用于等分显示子元素或按比例显示子元素的大小

    使用方法跟Android的android:layout_weight属性类似.可类比Android中的使用方法.这样比較好记,因为眼下全部浏览器都不支持大部分的属性,所以全部的属性都须要加上Firef ...

  4. 通达OA 小飞鱼OA实施法:以项目管理的方式来推进工作流设计项目实施

    做工作流设计的项目时,有时有几十个之多的流程须要做,并且时间有限,怎样把这些流程在有限的时间内设计完毕,并且达到预定要求成为这个项目须要解决的主要问题. 为了更好的完毕此次的工作流项目实施,在这里借鉴 ...

  5. html表格设计

    html部分,biaoge.html <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" " ...

  6. m_Orchestrate learning system---十四、数据表中字段命名规则

    m_Orchestrate learning system---十四.数据表中字段命名规则 一.总结 一句话总结:a.保证唯一 b.见名知意 1.注意php中的数组类函数和字符串类函数的前缀? 数组类 ...

  7. [雅礼NOIP2018集训] day6

    打满暴力好像是一种挑战,已经连续几天考试最后一个小时自闭了,因为自以为打完了暴力,然而,结果往往差强人意 大概是考试的策略有些问题 T1: 我们设$g[x]$为在x时取小于等于m个物品的最大价值,下面 ...

  8. FastJSON杂项

    //通过TypeReference解决泛型的问题 List<Integer> rst = JSON.parseObject(v,new TypeReference<List<I ...

  9. Android TextView加上阴影效果

    <TextView android:id="@+id/test_shadow" android:layout_width="wrap_content" a ...

  10. Linux 清空缓存

    sync echo 1 > /proc/sys/vm/drop_caches echo 2 > /proc/sys/vm/drop_caches echo 3 > /proc/sys ...