题意:

一棵10000个点的树,每条边的长不超过1000,给定一个值k,问距离不超过k的点对数有多少。(多组数据)

输入样例:

5 4
1 2 3
1 3 1
1 4 2
3 5 1
0 0 输出样例:
8 ————————————————————————————————————————————————————————————————————————————
这个题目是在CODEVS 2756 树上的路径 的学习过程中看到别人的题解的过程中看到的,这个题相对简单,是做那个题的基础。基本上是人家的代码,和抄也差不了多少。是学习树上的点分治的一个基础题。
根据一个大神漆子超的论文,树上的分治可以分为点分治,边分治和链分治。点分治最差log,边分治最差n。而链分治是最好的,不过没有学会,有空再从网上找来学习一下,就是只学习点皮毛,对自己做题思路也是一种扩展。
点分治,就是在树中去掉一个点,从而使原来的树变成更小的树,从而达到分治的目的。为了防止极差情况的出现,提高分治的效率,最好的分治点是树的重心(去掉该点后,所得最大子树最小)。所在就有了点分治的方法。
1、深搜,得到各个点为根的子树的大小和各个点的最大子树的大小
2、二次深搜,得到去掉各个点得到的最大子树的大小,从而通过遍历得到重心。
3、应用问题与重心的关系进行分治。
(本题中:
3.1、计算通过重心且不超过k的点对数(包含重边)。
3.2、减去过重心且不超过k的点对数(即有重边的点对数)。
3.3、标明已查到的重心(vis),在新生成的子树中重新进行上述操作,完成分治。
) 边分治,没有做过,不过据漆子超说,是去掉一条过,把树分成2个树,完成分治。个人愚见,如果不是星型那种极个别的情况也可以实现log。
————————————————————————————————————————————————————————————————————————————
 #include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm> using namespace std;
const int maxn=; int n,k,ans;
struct edge
{
int u,v,w,next;
}e[*maxn];
int head[maxn],js,jst,mi,root;
int siz[maxn],mx[maxn],dis[maxn];
bool vis[maxn];
void init()
{
memset(head,,sizeof(head));
memset(vis,,sizeof(vis));
js=;
ans=;
}
void readint(int &x)
{
int f=;
char c=getchar();
for(;c<''||c>'';c=getchar())if(c=='-')f=-f;
x=;
for(;c>=''&&c<='';c=getchar())x=x*+c-'';
x=x*f;
}
void addage(int u,int v,int w)
{
e[++js].u=u;e[js].v=v;e[js].w=w;
e[js].next=head[u];head[u]=js;
}
void dfssize(int u,int fa)
{
siz[u]=;mx[u]=;
for(int i=head[u];i;i=e[i].next)
{
int v=e[i].v;
if(v!=fa && !vis[v])
{
dfssize(v,u);
siz[u]+=siz[v];
if(siz[v]>mx[u])mx[u]=siz[v];
}
}
}
void dfsroot(int r,int u,int f)
{
if(siz[r]-siz[u]>mx[u])mx[u]=siz[r]-siz[u];
if(mx[u]<mi)
{
mi=mx[u];
root=u;
}
for(int i=head[u];i;i=e[i].next)
{
int v=e[i].v;
if(v!=f &&!vis[v])
{
dfsroot(r,v,u);
}
}
}
void dfsdis(int u,int d,int f)
{
dis[jst++]=d;
for(int i=head[u];i;i=e[i].next)
{
int v=e[i].v;
if(v!=f && !vis[v])
dfsdis(v,d+e[i].w,u);
}
}
int calc(int u,int d)
{
int anst=;
jst=;
dfsdis(u,d,);
sort(dis,dis+jst);
int i=,j=jst-;
while(i<j)
{
while(dis[i]+dis[j]>k && i<j)j--;
anst+=j-i;
i++;
}
return anst;
}
void dfs(int u)
{
mi=n;
dfssize(u,);
dfsroot(u,u,);
ans+=calc(root,);
vis[root]=;
for(int i=head[root];i;i=e[i].next)
{
int v=e[i].v;
if(!vis[v])
{
ans-=calc(v,e[i].w);
dfs(v);
} } }
int main()
{
while(scanf("%d%d",&n,&k)==)
{
if(!n && !k)break;
init();
for(int u,v,w,i=;i<n;i++)
{
readint(u);readint(v);readint(w);
addage(u,v,w);addage(v,u,w);
}
dfs();
printf("%d\n",ans);
}
return ;
}

poj1741 树上的点分治的更多相关文章

  1. POJ-1741 树上分治--点分治(算法太奇妙了)

    给你1e5个节点的树,(⊙﹏⊙) 你能求出又几对节点的距离小于k吗??(分治NB!) 这只是一个板子题,树上分治没有简单题呀!(一个大佬说的) #include<cstdio> #incl ...

  2. [POJ1741]树上的点对 树分治

    Description 给一棵有n个节点的树,每条边都有一个长度(小于1001的正整数). 定义dist(u,v)=节点u到节点v的最短路距离. 给出一个整数k,我们称顶点对(u,v)是合法的当且仅当 ...

  3. poj1741 树上的分治

    题意是说给了n个点的树n<=10000,问有多少个点对例如(a,b)他们的之间的距离小于等于k 采用树的分治做 #include <iostream> #include <cs ...

  4. poj1741 树上距离小于等于k的对数 点分治 入门题

    #include <iostream> #include <stdio.h> #include <string.h> #include <algorithm& ...

  5. POJ 1741 树上的点分治

    题目大意: 找到树上点对间距离不大于K的点对数 这是一道简单的练习点分治的题,注意的是为了防止点分治时出现最后分治出来一颗子树为一条直线,所以用递归的方法求出最合适的root点 #include &l ...

  6. POJ1741 Tree(树分治——点分治)题解

    题意:给一棵树,问你最多能找到几个组合(u,v),使得两点距离不超过k. 思路:点分治,复杂度O(nlogn*logn).看了半天还是有点模糊. 显然,所有满足要求的组合,连接这两个点,他们必然经过他 ...

  7. poj1741 Tree(点分治)

    题目链接:http://poj.org/problem?id=1741 题意:求树上两点之间距离小于等于k的点对的数量 思路:点分治模板题,推荐一篇讲的非常好的博客:https://blog.csdn ...

  8. POJ1741 tree 【点分治】

    Tree Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 25286   Accepted: 8421 Description ...

  9. [POJ1741]Tree(点分治模板)

    传送门 良心解析 其实以前在求某段序列上的区间统计问题时就碰到过类似于这样的思想. 当时的区间统计问题思路大致是这样: 选取一个点作为中间点,从这个点的左边和右边统计出满足条件的点对.然后当前的中间点 ...

随机推荐

  1. jQuery radio change事件 checkbox选中事件

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  2. 12 factor 目录

    I. 基准代码 一份基准代码,多份部署 II. 依赖 显式声明依赖关系 III. 配置 在环境中存储配置 IV. 后端服务 把后端服务当作附加资源 V. 构建,发布,运行 严格分离构建和运行 VI. ...

  3. java比较两个字符串是否相等

    从c 到c++ 到 c# 到 JavaScript  判断两个字符串是否相等,用==号都可以.奇葩的java怎么可以只能用equals()这个函数.只是因为String是引用类型吗??!!哭笑不得.. ...

  4. php读取出字符串中的img标签中的图片路径

    php读取出字符串中的img标签中的图片路径 $pageContents = '字符串,带img标签'; $pageContents = str_replace('\"','"', ...

  5. 114、Android禁止ViewPager的左右滑动

    有时候在开发中会遇到一些“诡异”的要求,比如在ViewPager中嵌入ListView,或者再嵌入一个ViewPager,那么在滑动的时候就会造成被嵌入的XXView不能滑动了,那么现在就把最外层的V ...

  6. 第五周PSP

    16号 类别c 内容c 开始时间s 结束e 中断I 净时间T GUI 学习QT视频 20:00 21:42 20m 82m 17号 类别c 内容c 开始时间s 结束e 中断I 净时间T GUI 学习Q ...

  7. ChartControl

    <dxc:ChartControl Name="chartControl1">            <dxc:ChartControl.Diagram>  ...

  8. ios delegate你必须知道的事情

    在我们的class中设计delegate的时候,我们通常会有几个注意事项. 假设我的class叫做MyClass,那我们可能会有定义一个MyClassDelegate这个protocol当作我的del ...

  9. 最牛B的编码套路

    最近,我大量阅读了Steve Yegge的文章.其中有一篇叫“Practicing Programming”(练习编程),写成于2005年,读后令我惊讶不已:   与你所相信的恰恰相反,单纯地每天埋头 ...

  10. 13. Reorder List

    Reorder List Given a singly linked list L: L0→L1→…→Ln-1→Ln, reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→… Y ...