题意:

一棵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. 快速理解Java中的五种单例模式

    解法一:只适合单线程环境(不好) package test; /** * @author xiaoping * */ public class Singleton { private static S ...

  2. java之main

    Java中用户向系统传递参数的三种基本方式 main方法 在Java中,main()方法是Java应用程序的入口方法,也就是说,程序在运行的时候,第一个执行的方法就是main()方法,这个方法和其他的 ...

  3. JS解析XML文件和XML字符串

    JS解析XML文件 <script type='text/javascript'> loadXML = function(xmlFile){ var xmlDoc=null; //判断浏览 ...

  4. POJ-2726-Holiday Hotel

    Holiday Hotel   Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 8302   Accepted: 3249 D ...

  5. SQL 创建一个只读账户 .

    1.进入sqlserver management studio 2.选择安全性->登录名->右键新建登录名 3.在常规里输入用户名和密码 4.在"用户映射"里“映射到此 ...

  6. FullCalendar只可以从外部拖入,内部不能互相拖动

    startDrag: function(ev) { if(ev.originalEvent.initEvent){ return; } if (!this.isListening) { // star ...

  7. C++编程命名规则(转载)

    原文地址:http://www.cnblogs.com/ggjucheng/archive/2011/12/15/2289291.html 如果想要有效的管理一个稍微复杂一点的体系,针对其中事物的一套 ...

  8. 【maven】之使用tomcat7-maven-plugin自动编译的问题

    今天遇到一个奇怪的问题,项目依赖关系如下, 在web端通过tomcat7插件debug模式启动项目的时候,dao层写的代码不能加载,还是原来的代码效果, 然后我在eclipse部署一个tomcat,将 ...

  9. oracle直通车第二周习题

    1.教材第二章课后作业 1,2,3,4题. 答:1. 创建一查询,显示与Blake在同一部门工作的雇员的项目和受雇日期,但是Blake不包含在内. 2. 显示位置在Dallas的部门内的雇员姓名.变化 ...

  10. Discuz有关问题解决办法汇总

    1.Can not write to cache files, please check directory ./data/ and ./data/cache/ . 无法写入缓存 解决办法:在sour ...