题目大意:给定一棵 N 个节点的无根树,边有边权,统计树上边权和不大于 K 的路径数。

对于每条树上路径,对于每一个点来说,该路径只有经过该点和不经过该点两种情况,对于不经过该点的情况,可以转化成是否经过以该点为树根的子树节点的子问题,由此构成一个分治策略。

对于点分治来说,限制算法复杂度的瓶颈之一是递归的层数,即:子问题的数目。因此,为了避免树退化成一条链,应该每次选取一棵树的重心作为根节点,进行递归求解。层数可以控制在 \(O(logn)\) 级别。

在统计经过每一个点的路径数量时,采用的策略是由该点出发,记录下以该点为根的子树中的每个点到该点的距离,排序后用双指针直接扫描记录贡献。考虑到路径必须经过该点,即:对于同一棵子树中的节点贡献值必须减去,因此在分治子树问题之前,先减去子树内部路径对答案的贡献。

代码如下

#include <vector>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define pb push_back
using namespace std;
const int maxn=1e4+10; int n,k,ans;
int sn,root,sz[maxn],f[maxn],dep[maxn];
bool vis[maxn];
vector<int> ret;
struct node{
int nxt,to,w;
node(int a=0,int b=0,int c=0):nxt(a),to(b),w(c){}
}e[maxn<<1];
int tot=1,head[maxn];
inline void add_edge(int from,int to,int w){
e[++tot]=node(head[from],to,w),head[from]=tot;
} void getroot(int u,int fa){
sz[u]=1,f[u]=0;
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(v==fa||vis[v])continue;
getroot(v,u);
f[u]=max(f[u],sz[v]);
sz[u]+=sz[v];
}
f[u]=max(f[u],sn-sz[u]);
if(!root||f[u]<f[root])root=u;
}
void getdis(int u,int fa){
ret.pb(dep[u]);
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to,w=e[i].w;
if(v==fa||vis[v])continue;
dep[v]=dep[u]+w;
getdis(v,u);
}
}
int calc(int u,int d){
dep[u]=d;
ret.clear();
getdis(u,0);
sort(ret.begin(),ret.end());
int cnt=0,l=0,r=ret.size()-1;
while(l<r){
if(ret[r]+ret[l]<=k)cnt+=r-l,++l;
else --r;
}
return cnt;
}
void dfs(int u){
vis[u]=1;
ans+=calc(u,0);
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to,w=e[i].w;
if(vis[v])continue;
ans-=calc(v,w);
root=0,sn=sz[v],getroot(v,0);
dfs(root);
}
} void read_and_parse(){
for(int i=1;i<n;i++){
int x,y,z;scanf("%d%d%d",&x,&y,&z);
add_edge(x,y,z),add_edge(y,x,z);
}
}
void solve(){
getroot(1,0);
dfs(root);
printf("%d\n",ans);
}
void init(){
memset(head,0,sizeof(head)),tot=1;
memset(vis,0,sizeof(vis));
root=ans=0,sn=n;
}
int main(){
while(scanf("%d%d",&n,&k)&&n&&k){
init();
read_and_parse();
solve();
}
return 0;
}

update at 2019.3.18

【POJ1741】Tree的更多相关文章

  1. 【POJ1741】Tree(点分治)

    [POJ1741]Tree(点分治) 题面 Vjudge 题目大意: 求树中距离小于\(K\)的点对的数量 题解 完全不觉得点分治了.. 简直\(GG\),更别说动态点分治了... 于是来复习一下. ...

  2. 【poj1741】 Tree

    http://poj.org/problem?id=1741 (题目链接) 题意 给出一个n个节点的带权树,求树上距离不超过K的所有点对的个数. solution  点分治裸题.所谓的点分治,就是对于 ...

  3. 【poj1741】Tree 树的点分治

    题目描述 Give a tree with n vertices,each edge has a length(positive integer less than 1001). Define dis ...

  4. 【POJ1741】Tree 树分而治之 模板略?

    做广告: #include <stdio.h> int main() { puts("转载请注明出处[vmurder]谢谢"); puts("网址:blog. ...

  5. 【POJ3237】Tree 树链剖分+线段树

    [POJ3237]Tree Description You are given a tree with N nodes. The tree's nodes are numbered 1 through ...

  6. 【BZOJ】【2631】Tree

    LCT 又一道名字叫做Tree的题目…… 看到删边加边什么的……又是动态树问题……果断再次搬出LCT. 这题比起上道[3282]tree的难点在于需要像线段树维护区间那样,进行树上路径的权值修改&am ...

  7. 【Luogu1501】Tree(Link-Cut Tree)

    [Luogu1501]Tree(Link-Cut Tree) 题面 洛谷 题解 \(LCT\)版子题 看到了顺手敲一下而已 注意一下,别乘爆了 #include<iostream> #in ...

  8. 【BZOJ3282】Tree (Link-Cut Tree)

    [BZOJ3282]Tree (Link-Cut Tree) 题面 BZOJ权限题呀,良心luogu上有 题解 Link-Cut Tree班子提 最近因为NOIP考炸了 学科也炸了 时间显然没有 以后 ...

  9. 【AtCoder3611】Tree MST(点分治,最小生成树)

    [AtCoder3611]Tree MST(点分治,最小生成树) 题面 AtCoder 洛谷 给定一棵\(n\)个节点的树,现有有一张完全图,两点\(x,y\)之间的边长为\(w[x]+w[y]+di ...

随机推荐

  1. 【下一代核心技术DevOps】:(七)持续集成Jenkins的应用(Aliyun Pipiline持续构建)

    1. 前言 使用Jenkins比较好的就是可以在整个构建顺序中增加自定义的动作,比如构建成功给Leader发个邮件,给团队核心发个微信什么的. 当然最基本的核心还是它可以构建多种开发语言的项目,此类构 ...

  2. Java 基础之一对象导论

    对象导论 1.1 抽象过程 所有编程语言都提供抽象机制.人们所能解决的问题的复杂性直接取决于抽象的类型和质量. 汇编语言是对底层机器的轻微抽象. 我们将问题空间中的元素及其再解空间中的表示称为对象.这 ...

  3. React.js 入门与实战课程思维导图

    原文发表于我的技术博客 我在慕课网的「React.js 入门与实战之开发适配PC端及移动端新闻头条平台」课程已经上线了,在这里分享了课程中的思维导图,供大家参考. 原文发表于我的技术博客 此导图为课程 ...

  4. DWR实现服务器向客户端推送消息

    原文链接 http://www.blogjava.net/stevenjohn/archive/2012/07/07/382447.html这片文章还是给了我很大帮助,再次表示感谢,下面我将这两天的研 ...

  5. [Intellij IDEA]_eclipse项目导入

    http://www.cnblogs.com/lindp/p/4484390.html

  6. Windows samba history

    https://blogs.technet.microsoft.com/josebda/2013/10/02/windows-server-2012-r2-which-version-of-the-s ...

  7. 其他数据库的restful方式

    1. mysql 的 xmysql https://blog.csdn.net/dev_csdn/article/details/78480522 2. Oracle 的ORDS https://bl ...

  8. [转帖]linux 内存管理——内核的shmall 和shmmax 参数

    (转)linux 内存管理——内核的shmall 和shmmax 参数   内核的 shmall 和 shmmax 参数 SHMMAX= 配置了最大的内存segment的大小 ------>这个 ...

  9. C从源码到运行发生了哪些事

    一个C/C++程序从源代码到可执行程序主要经历了四个阶段: ①预处理.包括展开宏.处理#include,#if,#ifdef等指令.删除注释.还有一些其他操作.相关命令:gcc -E或cpp ②编译. ...

  10. BZOJ2124 等差子序列(树状数组+哈希)

    容易想到一种暴力的做法:枚举中间的位置,设该位置权值为x,如果其两边存在权值关于x对称即合法. 问题是如何快速寻找这个东西是否存在.考虑仅将该位置左边出现的权值标1.那么若在值域上若关于x对称的两权值 ...