POJ1741 tree (点分治模板)
题目大意:
给一棵有 n 个顶点的树,每条边都有一个长度(小于 1001 的正整数)。
定义 dist(u,v)=节点 u 和 v 之间的最小距离。
给定一个整数 k,对于每一对 (u,v) 顶点当且仅当 dist(u,v) 不超过 k 时才称为有效。
编写一个程序,计算给定树有多少对有效。
算法分析:
这道题是一道标准的点分治模板题。题目给定的树是一颗无根树,我们首先选取点作为根节点,这里选取树的重心root作为划分点,使得将树划分得尽量均衡。然后我们统计每个点到根节点的距离,将这些距离加入到一个距离数组中,排序,用双指针扫描,就可以统计以root为根的满足条件的节点数,这里还要用到容斥的思想,我们对root的子树v都要减去重复统计的节点数,从v出发重复以上的过程。
要算两个节点之间的最小距离不超过k,以root为根,则有两种情况:
1.两个点在以root为根的同一颗子树中;
2.两个点在不同子树中;
1 #include<cstdio>
2 #include<cstring>
3 #include<algorithm>
4 using namespace std;
5 const int maxn=10005;
6 int cnt,n,k,ans,head[maxn];
7 int root,S,size[maxn],f[maxn],d[maxn],dep[maxn];
8 bool vis[maxn];
9 struct edge
10 {
11 int to,next,w;
12 }edge[maxn*2];
13
14 void add(int u,int v,int w)
15 {
16 edge[++cnt].to=v;
17 edge[cnt].w=w;
18 edge[cnt].next=head[u];
19 head[u]=cnt;
20 }
21
22 void getroot(int u,int fa)//获取重心
23 {
24 size[u]=1;
25 f[u]=0;//删除u后,最大子树的大小
26 for(int i=head[u];i;i=edge[i].next)
27 {
28 int v=edge[i].to;
29 if(v!=fa&&!vis[v])
30 {
31 getroot(v,u);
32 size[u]+=size[v];
33 f[u]=max(f[u],size[v]);
34 }
35 }
36 f[u]=max(f[u],S-size[u]);//S为当前子树总结点数
37 if(f[u]<f[root])
38 root=u;
39 }
40
41 void getdep(int u,int fa)//获取距离
42 {
43 dep[++dep[0]]=d[u];//保存距离数组
44 for(int i=head[u];i;i=edge[i].next)
45 {
46 int v=edge[i].to;
47 if(v!=fa&&!vis[v])
48 {
49 d[v]=d[u]+edge[i].w;
50 getdep(v,u);
51 }
52 }
53 }
54
55 int getsum(int u,int dis) //获取u的子树中满足个数
56 {
57 d[u]=dis;
58 dep[0]=0;
59 getdep(u,0);
60 sort(dep+1,dep+1+dep[0]);
61 int L=1,R=dep[0],sum=0;
62 while(L<R)
63 if(dep[L]+dep[R]<=k)
64 sum+=R-L,L++;
65 else
66 R--;
67 return sum;
68 }
69
70 void solve(int u) //获取答案
71 {
72 vis[u]=true;
73 ans+=getsum(u,0);
74 for(int i=head[u];i;i=edge[i].next)
75 {
76 int v=edge[i].to;
77 if(!vis[v])
78 {
79 ans-=getsum(v,edge[i].w);//减去重复
80 root=0;
81 S=size[v];
82 getroot(v,u);
83 solve(root);
84 }
85 }
86 }
87
88 int main()
89 {
90 f[0]=0x7fffffff;//初始化树根
91 while(scanf("%d%d",&n,&k),n+k)
92 {
93 memset(vis,0,sizeof(vis));
94 memset(head,0,sizeof(head));
95 cnt=0;ans=0;
96 for(int i=1;i<=n-1;i++)
97 {
98 int x,y,z;
99 scanf("%d%d%d",&x,&y,&z);
100 add(x,y,z);
101 add(y,x,z);
102 }
103 root=0;
104 S=n;
105 getroot(1,0);
106 solve(root);
107 printf("%d\n",ans);
108 }
109 return 0;
110 }
每次选取重心作为划分点,点分治最多递归O(logn)层,距离数组排序O(nlogn),总的时间复杂度O(n)。
POJ1741 tree (点分治模板)的更多相关文章
- POJ1741 Tree 树分治模板
http://poj.org/problem?id=1741 题意:一棵n个点的树,每条边有距离v,求该树中距离小于等于k的点的对数. dis[y]表示点y到根x的距离,v代表根到子树根的距离 ...
- [poj1741]Tree(点分治+容斥原理)
题意:求树中点对距离<=k的无序点对个数. 解题关键:树上点分治,这个分治并没有传统分治的合并过程,只是分成各个小问题,并将各个小问题的答案相加即可,也就是每层的复杂度并不在合并的过程,是在每层 ...
- POJ - 1741 - Tree - 点分治 模板
POJ-1741 题意: 对于带权的一棵树,求树中距离不超过k的点的对数. 思路: 点分治的裸题. 将这棵树分成很多小的树,分治求解. #include <algorithm> #incl ...
- [POJ1741]Tree(点分治)
树分治之点分治入门 所谓点分治,就是对于树针对点的分治处理 首先找出重心以保证时间复杂度 然后递归处理所有子树 对于这道题,对于点对(u,v)满足dis(u,v)<=k,分2种情况 路径过当前根 ...
- [bzoj1468][poj1741]Tree[点分治]
可以说是点分治第一题,之前那道的点分治只是模模糊糊,做完这道题感觉清楚了很多,点分治可以理解为每次树的重心(这样会把数分为若干棵子树,子树大小为log级别),然后统计包含重心的整个子树的值减去各个子树 ...
- bzoj 1468 Tree(点分治模板)
1468: Tree Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 1527 Solved: 818[Submit][Status][Discuss] ...
- [洛谷P4178] Tree (点分治模板)
题目略了吧,就是一棵树上有多少个点对之间的距离 \(\leq k\) \(n \leq 40000\) 算法 首先有一个 \(O(n^2)\) 的做法,枚举每一个点为起点,\(dfs\) 一遍可知其它 ...
- POJ1741 Tree + BZOJ1468 Tree 【点分治】
POJ1741 Tree + BZOJ1468 Tree Description Give a tree with n vertices,each edge has a length(positive ...
- poj1741 Tree(点分治)
题目链接:http://poj.org/problem?id=1741 题意:求树上两点之间距离小于等于k的点对的数量 思路:点分治模板题,推荐一篇讲的非常好的博客:https://blog.csdn ...
随机推荐
- 关于Tornado5.1:到底是真实的异步和还是虚假的异步
原文转载自「刘悦的技术博客」https://v3u.cn/a_id_107 我们知道Tornado 优秀的大并发处理能力得益于它的 web server 从底层开始就自己实现了一整套基于 epoll ...
- 选择结构——if控制语句单、双、多分支结构
1.if控制语句 概念: if控制语句共有3种不同形式,分别是单分支结构.双分支结构和多分支结构. (1)使用 if 语句实现单分支处理 语法格式: if(表达式){ 语句 } 流程图: 执行步骤: ...
- BMP位图之代码实现
从16位开始,不存在调色板,顶多存在一个RGBQUAD的掩码. 16位位图,我没有拿到对应的素材,但是根据官方文档的描述和代码验证后,我总结为下: 当biCompression为BI_RGB时,此时是 ...
- 使用fontforge修改字体,只保留数字
设计图上的数字采用了Roboto字体,原字体文件200多k,而小程序主包最大2m,承受不起这么大的字体.因为只用到了数字,所以可以使用fontforge编辑字体,删除多余的部分. 一.下载并安装fon ...
- ASP.NET Core 5.0中的Host.CreateDefaultBuilder执行过程
通过Rider调试的方式看了下ASP.NET Core 5.0的Web API默认项目,重点关注Host.CreateDefaultBuilder(args)中的执行过程,主要包括主机配置.应用程 ...
- Java学习--流程控制
Java学习 流程控制 用户交互Scanner Scanner对象 Java通过Scanner类获取用户的输入 基本语法: Scanner scanner = new Scanner(System.i ...
- 054_末晨曦Vue技术_处理边界情况之组件之间的循环引用
组件之间的循环引用 点击打开视频讲解更详细 假设你需要构建一个文件目录树,像访达或资源管理器那样的.你可能有一个 <tree-folder> 组件,模板是这样的: <p> &l ...
- Python小游戏——外星人入侵(保姆级教程)第一章 05重构模块game_functions
系列文章目录 第一章:武装飞船 05:重构:模块game_functions 一.重构 在大型项目中,经常需要在添加新代码前重构既有代码.重构旨在简化既有代码的结构,使其更容易扩展.在本节中,我们将创 ...
- 1.1_selenium+Python自动化测试大纲
- 【java】学习路径16-重写Object方法(equals()等)
在平时开发中,想要比较自定义类对象中的特定成员时,我们需要逐一手动比较,非常不方便. 举个栗子,我们有两个cafe对象,我们想比较两杯咖啡的价格是否一样,一般来说我们使用getter()来比较,但是这 ...