1468: Tree

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 1527  Solved: 818
[Submit][Status][Discuss]

Description

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

Input

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

Output

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

Sample Input

7
1 6 13
6 3 9
3 5 7
4 1 3
2 4 20
4 7 2
10

Sample Output

5
 
  1. /*
  2. 思路:
  3. 最容易想到的算法是:从每个点出发遍历整棵树,统计数对个数。
  4. 由于时间复杂度O(N^2),明显是无法满足要求的。
  5.  
  6. 对于一棵有根树, 树中满足要求的一个数对所对应的一条路径,必然是以下两种情况之一:
  7. 1、经过根节点
  8. 2、不经过根节点,也就是说在根节点的一棵子树中
  9. 对于情况2,可以递归求解,下面主要来考虑情况1。
  10.  
  11. 设点i的深度为Depth[i],父亲为Parent[i]。
  12. 若i为根,则Belong[i]=-1,若Parent[i]为根,则Belong[i]=i,否则Belong[i]=Belong[Parent[i]]。
  13. 这三个量都可以通过一次BFS求得。
  14. 我们的目标是要统计:有多少对(i,j)满足i<j,Depth[i]+Depth[j]<=K且Belong[i]<>Belong[j]
  15.  
  16. 如果这样考虑问题会变得比较麻烦,我们可以考虑换一种角度:
  17. 设X为满足i<j且Depth[i]+Depth[j]<=K的数对(i,j)的个数
  18. 设Y为满足i<j,Depth[i]+Depth[j]<=K且Belong[i]=Belong[j]数对(i,j)的个数
  19. 那么我们要统计的量便等于X-Y
  20.  
  21. 求X、Y的过程均可以转化为以下问题:
  22. 已知A[1],A[2],...A[m],求满足i<j且A[i]+A[j]<=K的数对(i,j)的个数
  23.  
  24. 对于这个问题,我们先将A从小到大排序。
  25. 设B[i]表示满足A[i]+A[p]<=K的最大的p(若不存在则为0)。我们的任务便转化为求出A所对应的B数组。那么,若B[i]>i,那么i对答案的贡献为B[i]-i。
  26. 显然,随着i的增大,B[i]的值是不会增大的。利用这个性质,我们可以在线性的时间内求出B数组,从而得到答案。
  27.  
  28. 综上,设递归最大层数为L,因为每一层的时间复杂度均为“瓶颈”——排序的时间复杂度O(NlogN),所以总的时间复杂度为O(L*NlogN)
  29.  
  30. 然而,如果遇到极端情况——这棵树是一根链,那么随意分割势必会导致层数达到O(N)级别,对于N=10000的数据是无法承受的。因此,我们在每一棵子树中选择“最优”的点分割。所谓“最优”,是指删除这个点后最大的子树尽量小。这个点可以通过树形DP在O(N)时间内求出,不会增加时间复杂度。这样一来,即使是遇到一根链的情况时,L的值也仅仅是O(logN)的。
  31.  
  32. 因此,改进后算法时间复杂度为O(Nlog^2N),可以AC。
  33. /*

学习 思路

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<algorithm>
  5.  
  6. #define inf 0x3f3f3f3f
  7. #define maxn 40010
  8.  
  9. using namespace std;
  10. struct node
  11. {
  12. int to,w,next;
  13. }e[maxn<<];
  14. int head[maxn],vis[maxn],son[maxn],deep[maxn],f[maxn],d[maxn];
  15. int n,cnt,root,sum,K,ans,num,x,y,z,L;
  16.  
  17. inline int read()
  18. {
  19. int x=,f=;char c=getchar();
  20. while(c>''||c<''){if(c=='-')f=-;c=getchar();}
  21. while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
  22. return x*f;
  23. }
  24.  
  25. inline void add(int u,int v,int dis)
  26. {
  27. e[++num].to=v;e[num].next=head[u];
  28. e[num].w=dis;head[u]=num;
  29. }
  30.  
  31. inline void init()
  32. {
  33. cnt=ans=root=sum=;
  34. memset(head,,sizeof(head));
  35. memset(vis,,sizeof(vis));
  36. memset(deep,,sizeof(deep));
  37. for(int i=;i<n;i++)
  38. {
  39. x=read();y=read();z=read();
  40. add(x,y,z);add(y,x,z);
  41. }
  42. }
  43.  
  44. void get_root(int now,int fa)
  45. {
  46. son[now]=;f[now]=-;
  47. for(int i=head[now];i;i=e[i].next)
  48. {
  49. int v=e[i].to;
  50. if(vis[v]||v==fa) continue;
  51. get_root(v,now);
  52. son[now]+=son[v];f[now]=max(f[now],son[v]);
  53. }
  54. f[now]=max(f[now],sum-son[now]);
  55. if(f[now]<f[root]) root=now;
  56. }
  57.  
  58. void get_deep(int now,int fa)
  59. {
  60. deep[++L]=d[now];
  61. for(int i=head[now];i;i=e[i].next)
  62. {
  63. int v=e[i].to;
  64. if(vis[v]||v==fa) continue;
  65. d[v]=d[now]+e[i].w;
  66. get_deep(v,now);
  67. }
  68. }
  69.  
  70. int cal(int now,int dis)
  71. {
  72. d[now]=dis;L=;get_deep(now,-);
  73. sort(deep+,deep+L+);
  74. int t=;
  75. for(int l=,r=L;l<r;)
  76. {
  77. if (deep[l]+deep[r]<=K) t+=r-l,l++;
  78. else r--;
  79. }
  80. return t;
  81. }
  82.  
  83. void work(int u)
  84. {
  85. ans+=cal(u,);vis[u]=;
  86. for(int i=head[u];i;i=e[i].next)
  87. {
  88. int v=e[i].to;
  89. if(vis[v]) continue;
  90. ans-=cal(v,e[i].w);sum=son[v];
  91. root=;get_root(v,);work(root);
  92. }
  93. }
  94.  
  95. int main()
  96. {
  97. freopen("data.txt","r",stdin);
  98. freopen("bzoj1468.txt","w",stdout);
  99. n=read();
  100. init();K=read();
  101. sum=n;f[]=inf;
  102. get_root(,-);
  103. work(root);
  104. printf("%d\n",ans);
  105. return ;
  106. }

代码

  1. #include<cstdio>
  2. #include<algorithm>
  3. #define N 40005
  4. using namespace std;
  5. struct arr{int s,go,next;}a[N*];
  6. int end[N],son[N],f[N],d[N],data[N];
  7. int cnt,L,All,ans,i,x,y,z,n,root,K;
  8. bool Can[N];
  9. void add(int u,int v,int s)
  10. {
  11. a[++cnt].go=v;a[cnt].next=end[u];a[cnt].s=s;end[u]=cnt;
  12. }
  13.  
  14. void Get_root(int k,int fa)
  15. {
  16. son[k]=;f[k]=;
  17. for (int i=end[k];i;i=a[i].next)
  18. {
  19. int go=a[i].go;
  20. if (go==fa||Can[go]) continue;
  21. Get_root(go,k);son[k]+=son[go];
  22. if (son[go]>f[k]) f[k]=son[go];
  23. }
  24. if (All-son[k]>f[k]) f[k]=All-son[k];
  25. if (f[k]<f[root]) root=k;
  26. }
  27.  
  28. void Get_array(int k,int fa)
  29. {
  30. data[++L]=d[k];
  31. for (int i=end[k];i;i=a[i].next)
  32. {
  33. int go=a[i].go;
  34. if (go!=fa&&!Can[go])
  35. d[go]=d[k]+a[i].s,Get_array(go,k);
  36. }
  37. }
  38.  
  39. int calc(int k,int now)
  40. {
  41. d[k]=now;L=;Get_array(k,-);
  42. int A=,l,r;
  43. sort(data+,data+L+);
  44. for (l=,r=L;l<r;)
  45. if (data[r]+data[l]<=K) A+=(r-l),l++;else r--;
  46. return A;
  47. }
  48.  
  49. void work(int k)
  50. {
  51. ans+=calc(k,);Can[k]=;
  52. for (int i=end[k];i;i=a[i].next)
  53. {
  54. int go=a[i].go;
  55. if (Can[go]) continue;
  56. ans-=calc(go,a[i].s);f[root=]=n+;
  57. All=son[go];Get_root(go,-);
  58. work(root);
  59. }
  60. }
  61.  
  62. int main()
  63. {
  64. freopen("data.txt","r",stdin);
  65. freopen("1468.txt","w",stdout);
  66. scanf("%d",&n);
  67. for (i=;i<n;i++)
  68. scanf("%d%d%d",&x,&y,&z),add(x,y,z),add(y,x,z);
  69. scanf("%d",&K);All=n;
  70. f[root=]=n+;Get_root(,-);
  71. work(root);
  72. printf("%d",ans);
  73. return ;
  74. }

标程

  1. #include <bits/stdc++.h>
  2.  
  3. using namespace std;
  4.  
  5. #define PaiChuCuoWuCaiBREAK true
  6.  
  7. int main()
  8. {
  9. while(PaiChuCuoWuCaiBREAK)
  10. {
  11. system("data.exe");
  12. system("1468.exe");
  13. system("bzoj1468.exe");
  14. if(system("fc 1468.txt bzoj1468.txt")) {cout<<"lrhdsb";break;}
  15. }
  16. return ;
  17. }

对拍

  1. #include <bits/stdc++.h>
  2.  
  3. using namespace std;
  4.  
  5. #define maxn 10004
  6. #define justval 68451
  7. #define justval_ 15641684
  8.  
  9. int l[maxn],r[maxn],n,lo,ro;
  10.  
  11. int main()
  12. {
  13. freopen("data.txt","w",stdout);
  14. n=rand()%maxn+;printf("%d\n",n);
  15. for(int i=;i<n;i++) l[i]=i+;
  16. lo=n-,r[++ro]=;
  17. for(int just=;just<n;just++)
  18. {
  19. int pos=rand()%lo+;
  20. int pos_=rand()%ro+;
  21. r[++ro]=l[pos];
  22. printf("%d %d %d\n",l[pos],r[pos_],rand()%justval);
  23. for(int i=pos;i<lo;i++) l[i]=l[i+];lo--;
  24. }
  25. printf("%d\n",rand()%justval_);
  26. return ;
  27. }

数据生成 一棵树

bzoj 1468 Tree(点分治模板)的更多相关文章

  1. BZOJ.1468.Tree(点分治)

    BZOJ1468 POJ1741 题意: 计算树上距离<=K的点对数 我们知道树上一条路径要么经过根节点,要么在同一棵子树中. 于是对一个点x我们可以这样统计: 计算出所有点到它的距离dep[] ...

  2. BZOJ 1468 Tree 【模板】树上点分治

    #include<cstdio> #include<algorithm> #define N 50010 #define M 500010 #define rg registe ...

  3. BZOJ 1468: Tree

    Description 真·树,问距离不大于 \(k\) 的点对个数. Sol 点分治. 同上. Code /********************************************* ...

  4. 【刷题】BZOJ 1468 Tree

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

  5. bzoj 1468 Tree 点分

    Tree Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1972  Solved: 1101[Submit][Status][Discuss] Desc ...

  6. POJ - 1741 - Tree - 点分治 模板

    POJ-1741 题意: 对于带权的一棵树,求树中距离不超过k的点的对数. 思路: 点分治的裸题. 将这棵树分成很多小的树,分治求解. #include <algorithm> #incl ...

  7. [洛谷P4178] Tree (点分治模板)

    题目略了吧,就是一棵树上有多少个点对之间的距离 \(\leq k\) \(n \leq 40000\) 算法 首先有一个 \(O(n^2)\) 的做法,枚举每一个点为起点,\(dfs\) 一遍可知其它 ...

  8. POJ1741 Tree 树分治模板

    http://poj.org/problem?id=1741   题意:一棵n个点的树,每条边有距离v,求该树中距离小于等于k的点的对数.   dis[y]表示点y到根x的距离,v代表根到子树根的距离 ...

  9. POJ1741 tree (点分治模板)

    题目大意: 给一棵有 n 个顶点的树,每条边都有一个长度(小于 1001 的正整数).定义 dist(u,v)=节点 u 和 v 之间的最小距离.给定一个整数 k,对于每一对 (u,v) 顶点当且仅当 ...

随机推荐

  1. linux安装mysql可视化工具MySQL-workbench 连接数据库 执行sql

    Step1:建立数据库连接 点击新建连接的按钮,符号是“+”的按钮,出现下图,在“Connection name”输入连接名称. 填写连接信息 输入数据库连接密码 测试连接: 再次点击连接时会要求输入 ...

  2. 快速搭建vue2.0+boostrap项目

    一.Vue CLI初始化Vue项目 全局安装vue cli npm install --global vue-cli 创建一个基于 webpack 模板的新项目 vue init webpack my ...

  3. Python - 三大器 迭代器,生层器,装饰器

    目录 Python - 三大器 迭代器,生层器,装饰器 一. 容器 二. 可迭代对象(iterable) 三. 迭代器 四. 生成器 五. 装饰器 1. 定义 六. 闭包 Python - 三大器 迭 ...

  4. 腾讯云,搭建LNMP环境

    LNMP代表的就是:Linux系统下Nginx+MySQL+PHP这种网站服务器架构. Linux是一类Unix计算机操作系统的统称,是目前最流行的免费操作系统.代表版本有:debian.centos ...

  5. 微信公众号:1-IDHTTP控件:GET/POST 请求获取access_token

    (图来源于方蓓?) 首先要理解公众号的流程.通过图知道,我们要:1.你要有个web服务器,用于和微信服务器通讯.你的web服务器必须让微信服务器能找到.2.通信要求按照微信公众号开发要求的格式提供相关 ...

  6. bupt summer training for 16 #1 ——简单题目

    D.What a Mess 给n个数,求其中能满足 a[i] % a[j] == 0 的数对之和 n = 1W,max_ai = 100W 不是很大,所以就直接筛就可以了 计算可得最高复杂度 < ...

  7. Mysql学习总结(40)——MySql之Select用法汇总

    一.条件筛选 1.数字筛选:sql = "Select * from [sheet1$] Where 销售单价 > 100" 2.字符条件:sql = "Selec ...

  8. 清北学堂模拟赛d1t3 听音乐(music)

    题目描述 LYK喜欢听音乐,总共有n首音乐,有m个时刻,每个时刻LYK会听其中一首音乐,第i个时刻会听第ai首音乐.它给自己定了一个规定,就是从听音乐开始,听的每连续n首音乐都是互不相同的.例如当n= ...

  9. 有用的生活有关的website

    1. 如何快速download mpa3 from youtube a. google "youtube download" 2. 打开https://y2mate.com 3. ...

  10. 文件上传-jquery.uploadify.js

    <script type="text/javascript" src="../jquery_uploadify/jquery.uploadify-3.1.min.j ...