【poj1741】 Tree
http://poj.org/problem?id=1741 (题目链接)
题意
给出一个n个节点的带权树,求树上距离不超过K的所有点对的个数。
solution
点分治裸题。所谓的点分治,就是对于一条路径,只有经过该点和不经过改点两种情况,所以我们可以通过找到树的重心,删去这个点,使树分成几棵小树,再递归处理。不经过的情况很好处理,直接递归到子树就可以了,关键是如何考虑经过的情况。
对于这道题,我们可以处理处所有点到当前子树重心的距离deep[],然后对于当前子树的两个节点i,j只要满足deep[i]+deep[j]<=K,便符合条件,此时我们发现,这样算出的解是经过当前子树重心的情况,而当i,j都是重心的同一棵儿子节点子树上的点时,会重复计算,因为待会又会递归处理这一子树。所以我们还要减去这一部分的点对,方法同上,只是缩小了树的范围。接着递归处理出解。
代码hzwer那里模来的,很多细节感觉处理的很优秀,我加了点注释。
代码
// poj1741
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#define MOD 1000000007
#define inf 2147483640
#define LL long long
#define free(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout);
using namespace std;
inline int getint() {
int x=0,f=1;char ch=getchar();
while (ch>'9' || ch<'0') {if (ch=='-') f=-1;ch=getchar();}
while (ch>='0' && ch<='9') {x=x*10+ch-'0';ch=getchar();}
return x*f;
} const int maxn=10010;
struct edge {int to,w,next;}e[maxn<<2];
int head[maxn],vis[maxn],son[maxn],deep[maxn],f[maxn],d[maxn],n,cnt,root,sum,K,ans; void insert(int u,int v,int w) {
e[++cnt].to=v;e[cnt].next=head[u];head[u]=cnt;e[cnt].w=w;
e[++cnt].to=u;e[cnt].next=head[v];head[v]=cnt;e[cnt].w=w;
}
void init() {
cnt=ans=root=sum=0;
memset(head,0,sizeof(head));
memset(vis,0,sizeof(vis));
memset(deep,0,sizeof(deep));
for (int i=1;i<n;i++) {
int u=getint(),v=getint(),w=getint();
insert(u,v,w);
}
}
void calroot(int u,int fa) { //找重心
f[u]=0;son[u]=1;
for (int i=head[u];i;i=e[i].next) {
if (fa==e[i].to || vis[e[i].to]) continue;
calroot(e[i].to,u);
son[u]+=son[e[i].to];
f[u]=max(f[u],son[e[i].to]);
}
f[u]=max(f[u],sum-son[u]);
if (f[u]<f[root]) root=u;
}
void caldeep(int u,int fa) { //统计当前树中每个节点到重心的距离
deep[++deep[0]]=d[u];
for (int i=head[u];i;i=e[i].next) {
if (e[i].to==fa || vis[e[i].to]) continue;
d[e[i].to]=d[u]+e[i].w;
caldeep(e[i].to,u);
}
}
int cal(int u,int now) {
d[u]=now;deep[0]=0;
caldeep(u,0);
sort(deep+1,deep+deep[0]+1);
int t=0;
for (int l=1,r=deep[0];l<r;) { //这里统计答案的方法很优秀
if (deep[l]+deep[r]<=K) t+=r-l,l++;
else r--;
}
return t;
}
void work(int u) {
ans+=cal(u,0); //统计当前树中所有符合条件的点对
vis[u]=1;
for (int i=head[u];i;i=e[i].next) if (!vis[e[i].to]) {
ans-=cal(e[i].to,e[i].w); //减掉在同一棵子树中的符合条件的节点
sum=son[e[i].to];
root=0;
calroot(e[i].to,0);
work(root); //递归分治处理子树
}
}
int main() {
while (scanf("%d%d",&n,&K)!=EOF && n) {
init();
sum=n;f[0]=inf;
calroot(1,0);
work(root);
printf("%d\n",ans);
}
return 0;
}
【poj1741】 Tree的更多相关文章
- 【POJ1741】Tree(点分治)
		[POJ1741]Tree(点分治) 题面 Vjudge 题目大意: 求树中距离小于\(K\)的点对的数量 题解 完全不觉得点分治了.. 简直\(GG\),更别说动态点分治了... 于是来复习一下. ... 
- 【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. ... 
- 【POJ1741】Tree
		题目大意:给定一棵 N 个节点的无根树,边有边权,统计树上边权和不大于 K 的路径数. 对于每条树上路径,对于每一个点来说,该路径只有经过该点和不经过该点两种情况,对于不经过该点的情况,可以转化成是否 ... 
- 【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 ... 
随机推荐
- HP PCS 云监控大数据解决方案
			——把数据从分散统一集中到数据中心 基于HP分布式并行计算/存储技术构建的云监控系统即是通过“云高清摄像机”及IaaS和PaaS监控系统平台,根据用户所需(SaaS)将多路监控数据流传送给“云端”,除 ... 
- 我理解的Hanlder--android消息传递机制
			每一个学习Android的同学都会觉得Handler是一个神奇的东西,我也一样,开始我以为我懂了Handler的机制,后来发现自己是一知半解,昨天想想,我能否自己实现一个Handler,让子线程与Ac ... 
- TCP/IP中最高大上的链路层简介(二)
			引言 对于程序猿来讲,似乎越接近底层,就越显得高大上.这也算是程序猿们的共同认知吧,虽然不是所有人.今天LZ就和各位一起探讨一下TCP/IP中最高大上的一层,也就是最底层的链路层. 这一层LZ了解的还 ... 
- PC互联网和移动互联网的本质差别
			网一代,我们先称为PC互联网,这大约可以从2010年作为分界,然后就是基于手机,及可穿戴的移动互联网. 在PC时代,软件都很庞大复杂,甚至客端端和网页混合,比如常见的桌面软件,Office及Photo ... 
- 一起来学node.js吧 node school简介
			node.js这几年火爆的简直丧心病狂,去lagou.com查查node.js的职位,那叫一个多. 要说火爆到什么程度,竟然有一个网站专门去教大家学习node.js, Node School. 进去逛 ... 
- js中什么时候回考虑用call或者apply
			这里我说出自己的浅薄的理解,希望大家可以共鸣! call一些装逼的用法: call的用法通常在两个地方会用到, 1.需要加一个层的时候,也可以不准确的说继承的时候,继承是继承父类的属性或者方法,而ao ... 
- JavaScript学习笔记-元素在滚动条滑动一定高度后自动置顶
			<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ... 
- JavaScript学习笔记-循环输出菱形,并可菱形自定义大小
			var Cen = 6;//定义菱形中部为第几行(起始值为0) //for循环输出菱形 document.write("<button onclick='xh()'>点我for循 ... 
- 富文本KidnEditor在MVC中的应用
			最近看到很多网站后台都用到了富文本,包括自己所在的公司也是.公司用的KindEditor,所以就讲讲KindEditor.之前我也没学过,所以网上搜了一篇博文,直接转载如下(PS:完全以学习为目的哦~ ... 
- LVS+MYCAT读写分离+MYSQL同步部署手册(第三版)
			1 配置MYSQL主备同步 1.1 测试环境 mysql版本:5.6.24: 操作系统内核版本:Linux-3.13-0-32 主数据库IP:192.168.10.3: 主数据库名:d ... 
