Tree
 

Description

Give a tree with n vertices,each edge has a length(positive integer less than 1001). 
Define dist(u,v)=The min distance between node u and v. 
Give an integer k,for every pair (u,v) of vertices is called valid if and only if dist(u,v) not exceed k. 
Write a program that will count how many pairs which are valid for a given tree. 

Input

The input contains several test cases. The first line of each test case contains two integers n, k. (n<=10000) The following n-1 lines each contains three integers u,v,l, which means there is an edge between node u and v of length l. 
The last test case is followed by two zeros. 

Output

For each test case output the answer on a single line.

Sample Input

5 4
1 2 3
1 3 1
1 4 2
3 5 1
0 0

Sample Output

8

Source

 
 
【题意】
  求树上两点间距离小等于K的方案数 (n<=10000)
 
【分析】
  经典的点分治问题。
  搞笑的我知道怎么做都纠集好久,纠结症怎么破。
  每层求重心方法分治是nlogn的。
  具体是,每次都只算lca为根的点对。
  设dis[x]为x节点到根的距离,那么我们求dis[x]+dis[y]<=k的方案数,并且x和y要在同子树上。
  先不考虑在不同子树上,直接求dis[x]+dis[y]<=k可以排序一次然后for一遍动态累加,然后再把同一棵子树上的方案数剪掉。
 
代码如下:
 #include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<cmath>
using namespace std;
#define Maxn 10010
#define INF 0xfffffff struct node
{
int x,y,c,next;
}t[Maxn*];int len;
int first[Maxn];
int n,k; int mymax(int x,int y) {return x>y?x:y;} void ins(int x,int y,int c)
{
t[++len].x=x;t[len].y=y;t[len].c=c;
t[len].next=first[x];first[x]=len;
}
int rt;
bool q[Maxn];
int sm[Maxn],mx[Maxn],dep[Maxn];
int v[Maxn],vl; void dfs(int x,int h,int f)
{
mx[x]=-;sm[x]=;
for(int i=first[x];i;i=t[i].next) if(t[i].y!=f&&q[t[i].y])
{
int y=t[i].y;//dep[y]=dep[x]+t[i].c;
dfs(y,h,x);
sm[x]+=sm[y];
mx[x]=mymax(mx[x],sm[y]);
}
mx[x]=mymax(mx[x],h-sm[x]);
if(mx[x]<mx[rt]) rt=x;
} int get_ans()
{
int now=,ans=;
sort(v+,v++vl);
for(int i=vl;i>=;i--)
{
if(now>i) now=i;
while(v[i]+v[now]<=k&&now<i) now++;
ans+=now-;
}
return ans;
} void dfs2(int x,int f)
{
v[++vl]=dep[x];
for(int i=first[x];i;i=t[i].next) if(t[i].y!=f&&q[t[i].y])
{
int y=t[i].y;
dep[y]=dep[x]+t[i].c;
dfs2(y,x);
}
} int fans; void ffind(int x,int f)
{
vl=;dep[x]=;dfs2(x,);
fans+=get_ans();
q[x]=;
for(int i=first[x];i;i=t[i].next) if(t[i].y!=f&&q[t[i].y])
{
int y=t[i].y;
vl=;dfs2(y,x);
fans-=get_ans();
}int i;
for(i=first[x];i;i=t[i].next)
if(t[i].y!=f&&q[t[i].y])
{
rt=;
dfs(t[i].y,x,sm[t[i].y]);
ffind(rt,x);
}
} int main()
{
while()
{
scanf("%d%d",&n,&k);
if(n==&&k==) break;
memset(first,,sizeof(first));
len=;
for(int i=;i<n;i++)
{
int x,y,c;
scanf("%d%d%d",&x,&y,&c);
ins(x,y,c);ins(y,x,c);
}
fans=;
memset(q,,sizeof(q));
mx[]=INF;
rt=;vl=;dfs(,n,);
ffind(rt,);
printf("%d\n",fans);
}
return ;
}

[POJ 1741]

其实不知道我打的点分治标不标准,感觉很丑。这题就有3个dfs,ffind是求分治的子树答案,dfs是求子树重心,dfs2是求dis以及把子树的dis加入到v中排序。

2016-10-16 22:16:44

【POJ 1741】 Tree (树的点分治)的更多相关文章

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

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

  2. POJ 1741 Tree 树的分治(点分治)

    题目大意:给出一颗无根树和每条边的权值,求出树上两个点之间距离<=k的点的对数. 思路:树的点分治.利用递归和求树的重心来解决这类问题.由于满足题意的点对一共仅仅有两种: 1.在以该节点的子树中 ...

  3. poj 1741(树的点分治)

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

  4. POJ 1741/1987 树的点分治

    树的点分治,主要思想是每次找子树的重心,计算经过根节点的情况数,再减去点对属于同一子树的情况. #include <iostream> #include <vector> #i ...

  5. POJ 1741.Tree 树分治 树形dp 树上点对

    Tree Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 24258   Accepted: 8062 Description ...

  6. POJ 1741 Tree 树的分治

    原题链接:http://poj.org/problem?id=1741 题意: 给你棵树,询问有多少点对,使得这条路径上的权值和小于K 题解: 就..大约就是树的分治 代码: #include< ...

  7. POJ 1741 Tree 树分治

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

  8. poj 1741 Tree (树的分治)

    Tree Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 30928   Accepted: 10351 Descriptio ...

  9. POJ 1741 Tree 树形DP(分治)

    链接:id=1741">http://poj.org/problem?id=1741 题意:给出一棵树,节点数为N(N<=10000),给出N-1条边的两点和权值,给出数值k,问 ...

  10. poj 1741 Tree(树的点分治)

    poj 1741 Tree(树的点分治) 给出一个n个结点的树和一个整数k,问有多少个距离不超过k的点对. 首先对于一个树中的点对,要么经过根结点,要么不经过.所以我们可以把经过根节点的符合点对统计出 ...

随机推荐

  1. (整理)FORM:Oracle EBS客制化Form的菜单栏用法说明

    用户最多可以定义45个form-level的trigger,名称必须为SPECIALn, 其中SPECIAL1 to SPECIAL15属于Tools菜单项,放在“工具”主菜单下. SPECIAL16 ...

  2. ACM/ICPC ZOJ1003-Crashing Balloon 解题代码

    #include <iostream> using namespace std; int main() { int **array = new int *[100]; for ( int ...

  3. springmvc中url-pattern的大坑

    <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springfr ...

  4. dbforge studio for mysql 怎样破解

    下载好dbforge studio压缩包有两个exe,dbforge.studio.for.mysql.6.0.315-loader.exe ,和dbforgemysql.exe,安装后目录在C:\P ...

  5. iOS开发——真机调试证书—发布证书

    (最近准备考试,空闲整理成博客……)

  6. OC - 5.内存管理

    一.引用计数器 1> 栈和堆 栈 ① 主要存储局部变量 ② 内存自动回收 堆 ① 主要存储需要动态分配内存的变量 ② 需要手动回收内存,是OC内存管理的对象 2> 简介 作用 ① 表示对象 ...

  7. IOS如何刷新视图上的显示内容

    大家都知道,UItableView 有个 reloadData的方法,可以tableview刷新视图.而普通的View上面.我们如何刷新视图的呢? 下图是我做的一个用户登录之后显示用户昵称和个性签名还 ...

  8. OC-手动内存管理

    一.为什么要进行内存管理 •移动设备的内存极其有限,每个app所能占用的内存是有限制的 • •下列行为都会增加一个app的内存占用 Ø创建一个OC对象 Ø定义一个变量 Ø调用一个函数或者方法 • •当 ...

  9. SpringMVC的文件上传

    首先导入jar包 在springMVC里面配置文件上传,以及限定上传文件的大小  <bean id="multipartResolver" class="org.s ...

  10. 数据挖掘-关联规则分析[ZZ]

    1.什么是关联规则 "尿布与啤酒"的故事大家都有听过,这里就不罗嗦了. 按常规思维,尿布与啤酒风马牛不相及,若不是借助数据挖掘技术对大量交易数据进行挖掘分析,沃尔玛是不可能发现数据 ...