【POJ1741】Tree
题目大意:给定一棵 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的更多相关文章
- 【POJ1741】Tree(点分治)
[POJ1741]Tree(点分治) 题面 Vjudge 题目大意: 求树中距离小于\(K\)的点对的数量 题解 完全不觉得点分治了.. 简直\(GG\),更别说动态点分治了... 于是来复习一下. ...
- 【poj1741】 Tree
http://poj.org/problem?id=1741 (题目链接) 题意 给出一个n个节点的带权树,求树上距离不超过K的所有点对的个数. solution 点分治裸题.所谓的点分治,就是对于 ...
- 【poj1741】Tree 树的点分治
题目描述 Give a tree with n vertices,each edge has a length(positive integer less than 1001). Define dis ...
- 【POJ1741】Tree 树分而治之 模板略?
做广告: #include <stdio.h> int main() { puts("转载请注明出处[vmurder]谢谢"); puts("网址:blog. ...
- 【POJ3237】Tree 树链剖分+线段树
[POJ3237]Tree Description You are given a tree with N nodes. The tree's nodes are numbered 1 through ...
- 【BZOJ】【2631】Tree
LCT 又一道名字叫做Tree的题目…… 看到删边加边什么的……又是动态树问题……果断再次搬出LCT. 这题比起上道[3282]tree的难点在于需要像线段树维护区间那样,进行树上路径的权值修改&am ...
- 【Luogu1501】Tree(Link-Cut Tree)
[Luogu1501]Tree(Link-Cut Tree) 题面 洛谷 题解 \(LCT\)版子题 看到了顺手敲一下而已 注意一下,别乘爆了 #include<iostream> #in ...
- 【BZOJ3282】Tree (Link-Cut Tree)
[BZOJ3282]Tree (Link-Cut Tree) 题面 BZOJ权限题呀,良心luogu上有 题解 Link-Cut Tree班子提 最近因为NOIP考炸了 学科也炸了 时间显然没有 以后 ...
- 【AtCoder3611】Tree MST(点分治,最小生成树)
[AtCoder3611]Tree MST(点分治,最小生成树) 题面 AtCoder 洛谷 给定一棵\(n\)个节点的树,现有有一张完全图,两点\(x,y\)之间的边长为\(w[x]+w[y]+di ...
随机推荐
- BugkuCTF sql注入
前言 写了这么久的web题,算是把它基础部分都刷完了一遍,以下的几天将持续更新BugkuCTF WEB部分的题解,为了不影响阅读,所以每道题的题解都以单独一篇文章的形式发表,感谢大家一直以来的支持和理 ...
- C_数据结构_循环实现求阶乘
# include <stdio.h> int main(void) { int val; printf("请输入一个数字:"); printf("val = ...
- Python-列表-9
列表: Why: 我们现在已经学过的数据类型有:数字,布尔值,字符串,大家都知道数字主要用于计算,bool值主要是条件判断,只有字符串可以用于数据的存储,这些数据类型够用么?对于一门语言来说,肯定是不 ...
- Note: SE Class's Individual Project
虽然第一个Project还有点小问题需要修改,但是大体已经差不多了,先把blog记在这里,算是开博第一篇吧! 1.项目预计的用时 本来看到这个题的时候想的并不多,但是看了老师的要求才觉得如此麻烦ORZ ...
- linux内核分析第六周学习笔记
LINUX内核分析第六周学习总结 标签(空格分隔): 20135328陈都 陈都 原创作品转载请注明出处 <Linux内核分析>MOOC课程 http://mooc.study.163.c ...
- Unigine mesh顶点坐标转换精度问题
本问题虽然与Unigine引擎相关,但对其他精度问题也有参考价值. 问题: 将精细模型顶点从自身参考系的相对坐标(类似4378.95020,4561.00000,31.3887463) 转到椭球面世界 ...
- NSLog debug时打印 release时不打印
创建.h文件,添加以下代码 #ifdef DEBUG #define NSLog(...) NSLog(__VA_ARGS__) #else #define NSLog(...) {} #end ...
- PAT 1057 数零壹
https://pintia.cn/problem-sets/994805260223102976/problems/994805270914383872 给定一串长度不超过 105 的字符串, ...
- Daemon Thread [shirocache] (Running)
shiro cache的原理 https://cwiki.apache.org/confluence/display/SHIRO/Caching shirocache这个线程相关的内容
- intval()和int()
int intval ( mixed $var [, int $base ] ) 通过使用特定的进制转换(默认是十进制),参数base表示进制,只有当var是字符串时,base才会有意义,表示按 ...