题目给一棵边带权的树,统计路径长度<=k的点对数。

楼教主男人八题之一,分治算法在树上的应用。

一开始看论文看不懂,以为重心和距离那些是一遍预处理得来的。。感觉上不敢想每棵子树都求一遍重心和距离——那样时间复杂度怎么会只有O(nlogn)?

后来想通了,真的是对于每颗子树都把其所有结点单独提取出来,而且这么做就是O(nlogn)!

  • 首先每次都选择重心进行分治,这样最多大概处理logn层,每一层都包含若干棵子树;
  • 考虑每一层的每棵子树要提取的结点个数的和:第一层:n,第二层:n-1(第一层子树个数),第三层:n-(第一层子树个数+第二层子树个数)……不妨就认为每一层都有n个结点的信息要处理,而有logn层,所以其实总共就只有nlogn个(次)结点要处理;
  • 对于每一层每棵子树求重心的时间复杂度是线性的,而每层n个结点,最多logn层,所以求重心时间的复杂度就是O(nlogn);
  • 对于这道题子树要计算的信息是各个结点到根的距离,然后对其排序并在线性时间复杂度统计点对数目,其处理每棵子树时间复杂度是O(xlogx),x为该子树结点个数;不妨设某层各个子树结点个数为a、b、c……,而a+b+c+……=n,则aloga+blogb+clogc<=nlogn,共logn层,所以处理所有层所有子树信息的时间复杂度就是O(nlog2n);
  • 故这一题用点分治的时间复杂度是O(nlog2n)!

写这一题,捋清思路后分了好几个函数逐一实现,感觉框架挺清晰的,提交之后就1A还是很爽的。

 #include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define INF (1<<30)
#define MAXN 11111 struct Edge{
int v,w,next;
}edge[MAXN<<];
int NE,head[MAXN];
void addEdge(int u,int v,int w){
edge[NE].v=v; edge[NE].w=w; edge[NE].next=head[u];
head[u]=NE++;
} int n,k,ans;
bool vis[MAXN]; int centre,minimum,size[MAXN];
void getSize(int u,int fa){
size[u]=;
for(int i=head[u]; i!=-; i=edge[i].next){
int v=edge[i].v;
if(v==fa || vis[v]) continue;
getSize(v,u);
size[u]+=size[v];
}
}
void getCentre(int u,int fa,int &tot){
int res=tot-size[u];
for(int i=head[u]; i!=-; i=edge[i].next){
int v=edge[i].v;
if(v==fa || vis[v]) continue;
res=max(res,size[v]);
getCentre(v,u,tot);
}
if(minimum>res){
minimum=res;
centre=u;
}
} int a[MAXN],b[MAXN],an,bn;
void dfs(int u,int fa,int dist){
a[an++]=b[bn++]=dist;
for(int i=head[u]; i!=-; i=edge[i].next){
int v=edge[i].v;
if(v==fa || vis[v]) continue;
dfs(v,u,dist+edge[i].w);
}
}
int count(int *c,int &cn){
sort(c,c+cn);
int res=,i=,j=cn-;
while(i<j){
while(i<j && c[i]+c[j]>k) --j;
res+=j-i;
++i;
}
return res;
} void conquer(int u){
an=; a[an++]=;
for(int i=head[u]; i!=-; i=edge[i].next){
int v=edge[i].v;
if(vis[v]) continue;
bn=;
dfs(v,u,edge[i].w);
ans-=count(b,bn);
}
ans+=count(a,an);
}
void divide(int u){
getSize(u,u); minimum=INF; getCentre(u,u,size[u]);
u=centre;
vis[u]=;
conquer(u);
for(int i=head[u]; i!=-; i=edge[i].next){
int v=edge[i].v;
if(vis[v]) continue;
divide(v);
}
} int main(){
int a,b,c;
while(scanf("%d%d",&n,&k),(n||k)){
NE=;
memset(head,-,sizeof(head));
for(int i=; i<n; ++i){
scanf("%d%d%d",&a,&b,&c);
addEdge(a,b,c); addEdge(b,a,c);
}
ans=;
memset(vis,,sizeof(vis));
divide();
printf("%d\n",ans);
}
return ;
}

POJ1741 Tree(树的点分治)的更多相关文章

  1. POJ1741——Tree(树的点分治)

    1 /* *********************************************** 2 Author :kuangbin 3 Created Time :2013-11-17 1 ...

  2. 【poj1741】Tree 树的点分治

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

  3. hdu 4812 D Tree(树的点分治)

    D Tree Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 102400/102400 K (Java/Others) Total ...

  4. [poj1741][tree] (树/点分治)

    Description Give a tree with n vertices,each edge has a length(positive integer less than 1001). Def ...

  5. POJ1741 Tree 树分治模板

    http://poj.org/problem?id=1741   题意:一棵n个点的树,每条边有距离v,求该树中距离小于等于k的点的对数.   dis[y]表示点y到根x的距离,v代表根到子树根的距离 ...

  6. POJ1741(SummerTrainingDay08-G 树的点分治)

    Tree Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 23380   Accepted: 7748 Description ...

  7. hdu4812-D Tree (树的点分治)

    昨天学了下树分治,今天补这道题,还是太不熟练了,写完之后一直超时.后来查出好多错= =比如v,u写倒了,比如+写成了取最值,比如....爆int...查了两个多小时的错..哭...(没想到进首页了 h ...

  8. 【POJ 1741】 Tree (树的点分治)

    Tree   Description Give a tree with n vertices,each edge has a length(positive integer less than 100 ...

  9. 树上点对统计poj1741(树的点分治)

    给定一棵树,边上有权值,要统计有多少对点路径的权值和<=k 分治算法在树的路径中的应用 这个论文里面有分析. 任意两点的路径,要么过根结点,要么在子树中.如果在子树中,那么只要递归处理就行了. ...

  10. POJ 1741 Tree(树的点分治,入门题)

    Tree Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 21357   Accepted: 7006 Description ...

随机推荐

  1. python使用工具简介介绍

    我从研究生开学以来就开始在学python,现在来简单分享下一些基本的使用命令和快捷方式 Pycharm: 运行程序 ctrl+alt+F10 删除一行ctrl+D 注释ctrl+/ 安装python所 ...

  2. python爬取动态网页2,从JavaScript文件读取内容

    import requests import json head = {"user-agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) ...

  3. React02

    目录 React 进阶提升 条件渲染 受控组件* 状态提升* 组件数据流 TODO-LIST 设置服务器端口 列表渲染 条目PropTypes检查类型 export & import Refs ...

  4. MVC3使用Area解耦项目

    源代码 1.增加AreasChildRegistration类,类继承PortableAreaRegistration 2.增加引用MvcContrib 3.主项目中Area文件夹下增加Web.con ...

  5. 网络--TIME_WAIT状态

    MSL时间 MSL就是maximum segment lifetime(最大分节生命期),这是一个IP数据包能在互联网上生存的最长时间,超过这个时间IP数据包将在网络中消失 .MSL在RFC 1122 ...

  6. Dijkstra算法_最短路径_L2-001. 紧急救援

    作为一个城市的应急救援队伍的负责人,你有一张特殊的全国地图.在地图上显示有多个分散的城市和一些连接城市的快速道路.每个城市的救援队数量和每一条连接两个城市的快速道路长度都标在地图上.当其他城市有紧急求 ...

  7. J2EE的十三种技术——JDBC

    背景: 之前准备软考的时候,我们就学习过J2SE的视频.在进入J2EE之前,一定要复习和回顾下Java的基础知识,这对以后的学习十分重要.首先,简单回忆下java的体系结构.Java有三个体系结构:J ...

  8. (总结)统计Apache或Nginx访问日志里的独立IP访问数量的Shell

    1.把IP数量直接输出显示:cat access_log_2011_06_26.log |awk '{print $1}'|uniq -c|wc -l 2.把IP数量输出到文本显示:cat acces ...

  9. POJ 3180 The cow Prom Tarjan基础题

    题目用google翻译实在看不懂 其实题目意思如下 给一个有向图,求点个数大于1的强联通分量个数 #include<cstdio> #include<algorithm> #i ...

  10. P4397 [JLOI2014]聪明的燕姿

    P4397 [JLOI2014]聪明的燕姿 题目背景 阴天傍晚车窗外 未来有一个人在等待 向左向右向前看 爱要拐几个弯才来 我遇见谁会有怎样的对白 我等的人他在多远的未来 我听见风来自地铁和人海 我排 ...