还有两天就要去FJWC啦…

题意:一颗无根树,$k$为给定常数,求树上距离不超过$k$的点对的数量,多组数据,$n \leq 10^4$.


应该是点分治经典题~

一般对于无根树我们都可以把它转变成有根树(其实树上路径不管哪个根都一样嘛),假设我们已经钦定了一个根$rot$(后面会说其实这个根应该是重心),对于$rot$这颗树中的对答案有贡献的路径,要么经过$rot$,要么直接就是$rot$的某一颗子树的答案,这两种情况之间没有交集直接相加,这里就出现了子问题。

而对于经过$rot$的路径的贡献,对可以通过处理一遍$rot$的子树里到它的距离$dis[]$在$O(nlogn)$时间内统计(具体见代码,其实就排个序然后扫描)。这样对于每个点我们只要找根,处理经过$rot$的路径的答案(1),删除$rot$然后递归对$rot$的所有相邻点$cur$递归的求答案(2),不过这里出现了重复计算(设$w$为当前点到相邻点$cur$的边的长度):在(1)当中其实重复计算了$cur$里满足$dis[x]+w+dis[y]+w \leq k$的点对多算了,所以我们还要减掉这种答案(你问我怎么减?看代码啦~)

实现删除的时候有个trick就是用一个数组$vis[]$来记录这个点处理过没…处理过了直接不管它。

时间复杂度?假设最多递归了$T$层,计算每一层的答案一定不超过$O(nlogn)$,总复杂度就变成了$O(T*nlogn)$。如果随便钦定某个根递归层数太大的话会被卡成$O(n^2logn)$的,嗯那么要让递归层数小的话当然就选择这个子树的重心啦~每次$O(n)$的算重心,这样$x$的所有子树的大小都不会超过整棵树大小的一半,所以深度就是$(logn)$的了,总复杂度$O(nlog^2 n)$~

呼~

#include<cstdio>
#include<cstring>
#include<algorithm>
#define rep(i,n) for(register int i=1;i<=n;i++)
using namespace std;
const int N=10005;
inline int read()
{
int s=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=0;c=getchar();}
while(c>='0'&&c<='9'){s=s*10+c-'0';c=getchar();}
return f?s:-s;
}
struct edge
{
int to,nxt,w;
edge(int to=0,int nxt=0,int w=0):to(to),nxt(nxt),w(w){}
}edges[N<<1];
int n,k,cnt,tot;
int head[N<<1],dis[N],size[N],g[N],vis[N]; inline void addEdge(int u,int v,int w)
{
edges[++cnt]=edge(v,head[u],w);
head[u]=cnt;
}
#define cur edges[i].to
inline void dfs_root(int x,int f)
{
size[x]=1;g[x]=0;
for(register int i=head[x];i;i=edges[i].nxt)if(!vis[cur]&&cur!=f)
{
dfs_root(cur,x);size[x]+=size[cur];
g[x]=max(g[x],size[cur]);
}
}
inline int calc_root(int x,int f,int rot)
{
int res=0,minx=n;
for(register int i=head[x];i;i=edges[i].nxt)if(!vis[cur]&&cur!=f)
{
int tmp=calc_root(cur,x,rot);
if(g[tmp]<minx)minx=g[tmp],res=tmp;
}
g[x]=max(g[x],size[rot]-size[x]);
if(g[x]<minx)minx=g[x],res=x;
return res;
}
inline int get_root(int x)
{
dfs_root(x,-1);
return calc_root(x,-1,x);
}
inline void dfs_dis(int x,int d,int f)
{
dis[++tot]=d;
for(register int i=head[x];i;i=edges[i].nxt)
if(!vis[cur]&&cur!=f)dfs_dis(cur,d+edges[i].w,x);
}
inline int calc(int x,int w)
{
tot=0;
dfs_dis(x,w,-1);sort(dis+1,dis+tot+1);
int j=tot,res=0;
for(register int i=1;i<=j;i++)
{
while(i<j&&dis[i]+dis[j]>k)j--;
res+=j-i;
}return res;
}
inline int dfs(int x)
{
int rot=get_root(x),res=0;
vis[rot]=1;
res+=calc(rot,0);
for(register int i=head[rot];i;i=edges[i].nxt)if(!vis[cur])
{
res-=calc(cur,edges[i].w);//算距离的时候多加个变量就行啦
//注意不要把两种合起来写…一个是rot的子树一个是cur的子树
res+=dfs(cur);
}
return res;
} #undef cur
int main()
{
while(scanf("%d%d",&n,&k)==2&&(n+k))
{
cnt=0;
rep(i,n-1)
{
int u,v,w;u=read();v=read();w=read();
addEdge(u,v,w);addEdge(v,u,w);
}
printf("%d\n",dfs(1));
rep(i,cnt)head[i]=0;rep(i,n)vis[i]=0;
}
return 0;
}

[日常摸鱼]poj1741Tree-点分治的更多相关文章

  1. [日常摸鱼]Vijos1083小白逛公园-线段树

    题意:单点修改,询问区间最大子段和,$n\leq 5e5$ 考虑分治的方法$O(nlogn)$求一次最大子段和的做法,我们是根据中点分成左右两个区间,那么整个区间的答案要么是左边答案,要么是右边答案, ...

  2. Hash 日常摸鱼笔记

    本篇文章是Hash在信息学竞赛中的应用的学习笔记,分多次更新(已经有很多坑了) 一维递推 首先是Rabin-Karp,对于一个长度为\(m\)的串\(S\) \(f(S)=\sum_{i=1}^{m} ...

  3. [日常摸鱼]HDU1724 Ellipse-自适应Simpson法

    模板题~ QAQ话说Simpson法的原理我还是不太懂-如果有懂的dalao麻烦告诉我~ 题意:每次给一个椭圆的标准方程,求夹在直线$x=l$和$x=r$之间的面积 Simpson法 (好像有时候也被 ...

  4. [日常摸鱼]bzoj1257余数之和

    题意:输入$k,n$,求$\sum_{i=1}^n k \mod i$ $k \mod i=k-i*\lfloor \frac{k}{i} \rfloor $,$n$个$k$直接求和,后面那个东西像比 ...

  5. [日常摸鱼]bzoj1001狼抓兔子-最大流最小割

    题意就是求最小割- 然后我们有这么一个定理(最大流-最小割定理 ): 任何一个网络图的最小割中边的容量之和等于图的最大流. (下面直接简称为最大流和最小割) 证明: 如果最大流>最小割,那把这些 ...

  6. [日常摸鱼]pojKaka's Matrix Travels-拆点+最大费最大流

    方格取数的升级版,每个格子最多取一次. $k=1$的话就是个普及组的dp题,$k=2$就是在之前的基础上多加两维. 然而现在$k$太大了当然就不dp啦 对于$k=1$的情况我们还可以把$(i,j)$向 ...

  7. [日常摸鱼]loj6000「网络流 24 题」搭配飞行员

    题面 应该是二分图匹配,不过我写的是网络最大流. dinic求二分图最大匹配:加个源点和汇点,源点连向二分图的一边所有点,二分图的另一边所有点连向汇点,很明显这样得到的最大流就是这个二分图的最大匹配. ...

  8. [日常摸鱼]bzoj1218[HNOI2003]激光炸弹-二维前缀

    题意:二维网格一些格子有权值,求用边长为$r$的正方形能覆盖到格子权值和的最大值,格子大小$ \leq 5000$ 非常裸的二维前缀,然而 题目下标从0开始! QAQ 要是比赛就要爆零啦- #incl ...

  9. [日常摸鱼]bzoj2724蒲公英-分块

    区间众数经典题~ http://begin.lydsy.com/JudgeOnline/problem.php?id=4839这里可以提交~ 题意大概就是没有修改的询问区间众数,如果有一样的输出最小的 ...

随机推荐

  1. 2020阿里,字节跳动,JAVA岗(一线企业校招、社招)面试题合集

    前言 以下面试题全属于一线大厂社招以及校招的面试真题,各位在做这些题目对照自己的时候请平凡心对待,不要信心受挫.其实 做为致力于一线企业校招或者社招的你来说,能把每个知识模块的一小部分问题去深入学习和 ...

  2. java大厂面经-阿里腾讯、网易美团、京东、华为、快手、字节全在这里了

    前言 在这篇文章详细说了该如何去复习,之前也答应各位把面经整理一下,但是因为入职的事情耽搁了,现在整理出来回馈给大家! 美团 一面 0.自我介绍1.问项目(项目详细介绍.用到什么技术.有什么优化)2. ...

  3. 「LOJ 539」「LibreOJ NOIP Round #1」旅游路线

    description 题面较长,这里给出题目链接 solution 考虑预处理出\(f[i][j]\)表示在第\(i\)个点加满油后,从第\(i\)个点出发,至多消耗\(j\)元钱走过的最大路程,那 ...

  4. 【P2634】聪聪可可——点分治

    (题面来自Luogu) 题目描述 聪聪和可可是兄弟俩,他们俩经常为了一些琐事打起来,例如家中只剩下最后一根冰棍而两人都想吃.两个人都想玩儿电脑(可是他们家只有一台电脑)--遇到这种问题,一般情况下石头 ...

  5. 放进你的收藏夹吃灰!Linux 运维必备的 40 个命令总结

    1.删除0字节文件 find -type f -size 0 -exec rm -rf {} ; 2.查看进程 按内存从大到小排列 PS -e -o "%C : %p : %z : %a&q ...

  6. Qt5字符串编码转换学习

    目录 1.通过Python3示例探索常用字符串编码 UTF8 ANSI Unicode 小结 2.Qt5中使用QTextCodec进行编码转换 小结 1.通过Python3示例探索常用字符串编码 下面 ...

  7. 冲刺随笔——Day_Three

    这个作业属于哪个课程 软件工程 (福州大学至诚学院 - 计算机工程系) 这个作业要求在哪里 团队作业第五次--Alpha冲刺 这个作业的目标 团队进行Alpha冲刺 作业正文 正文 其他参考文献 无 ...

  8. 关于javaSMTP协议发邮件你必须知道的知识点

    1.阅读官方吐槽 Note also that THERE IS NOT SUFFICIENT DOCUMENTATION HERE TO USE THESE FEATURES!!! You will ...

  9. 第八章 Python类中常用的特殊变量和方法

    上章花了近三十章节介绍类的知识,本章估计内容也比较多,讲完这些,其实还有更多.为什么这么多类有关的知识呢,这是因为在Python里面一切皆对象,就连整型.浮点数.字符串这些比较常规的类型都是作为类来实 ...

  10. 第三十六章、PyQt输入部件:QAbstractSpinBox派生类QSpinBox、 QDoubleSpinBox、QDateTimeEdit、QDateEdit和QTimeEdit

    专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 老猿学5G博文目录 一.概述 Designer输入部件中的Spin B ...