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

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

 
题意:一棵有n个结点的树,求距离不超过k的点对
思路:树分治。n比较大,直接枚举所有点对肯定是不行的。按照重心把树分成若干子树,那么所有的点对一定属于 1)点u、v属于同一子树的点对; 2)点u、v属于不同子树的定点对; 3)重心s和其他点组成点对。1)情况可以通过递归得到。2)情况,只要先求出每个点到重心s的距离,就可以统计出和不超过k的点对数。而3)情况,添加一个0的顶点,就成为了情况2)。需要注意的是,需要避免重复统计,即应该在1)中统计的属于同一子树的点对,要避免在2)中进行统计。递归深度最多为log(n)层,每层总共有n个结点。
代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<set>
#include<bitset>
#include<map>
#include<queue>
#include<stack>
#include<vector>
using namespace std;
#define bug(x) cout<<"bug"<<x<<endl;
#define PI acos(-1.0)
#define eps 1e-8
typedef long long ll;
typedef pair<int,int> P;
const int N=1e5+,M=1e5+;
const int inf=0x3f3f3f3f;
const ll INF=1e18+,mod=1e9+;
struct edge
{
int from,to;
int w;
int next;
};
edge es[M];
int cut,head[N];
int si[N],maxx[N];
bool vis[N];
int deep[N];
int k;
int root,ans;
void init()
{
cut=;
memset(head,-,sizeof(head));
}
void addedge(int u,int v,int w)
{
cut++;
es[cut].from=u,es[cut].to=v;
es[cut].w=w;
es[cut].next=head[u];
head[u]=cut;
}
int getroot(int u,int fa,int n)
{
si[u]=,maxx[u]=;
for(int i=head[u]; i!=-; i=es[i].next)
{
int v=es[i].to;
if(v==fa||vis[v]) continue;
si[u]+=getroot(v,u,n);
maxx[u]=max(maxx[u],si[v]);
}
maxx[u]=max(maxx[u],n-si[u]);
if(maxx[u]<maxx[root]) root=u;
return si[u];
}
void getdeep(int u,int fa,int d)
{
deep[++deep[]]=d;
for(int i=head[u]; i!=-; i=es[i].next)
{
edge e=es[i];
if(e.to==fa||vis[e.to]) continue;
getdeep(e.to,u,d+e.w);
}
}
int cal(int u,int fa,int d)
{
deep[]=;
getdeep(u,fa,d);
sort(deep+,deep+deep[]+);
int l=,r=deep[];
int res=;
while(l<r)
{
if(deep[l]+deep[r]<=k) res+=r-l,l++;
else r--;
}
return res;
}
void solve(int u)
{
vis[u]=true;
ans+=cal(u,,);///统计符合情况的点对数
for(int i=head[u]; i!=-; i=es[i].next)
{
edge e=es[i];
if(vis[e.to]) continue;
ans-=cal(e.to,,e.w);///删除同一子树的点对数
root=;
getroot(e.to,,si[e.to]);
solve(root);///递归同一子树
}
}
int main()
{
int n;
while(scanf("%d%d",&n,&k)!=EOF)
{
if(n==&&k==) break;
init();
for(int i=; i<n; i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
addedge(u,v,w);
addedge(v,u,w);
}
memset(vis,false,sizeof(vis));
root=,maxx[]=inf;
ans=;
getroot(,,n);
solve(root);
printf("%d\n",ans);
}
return ;
}

树分治

POJ 1741.Tree 树分治 树形dp 树上点对的更多相关文章

  1. POJ 1741 Tree 树分治

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

  2. 树的点分治 (poj 1741, 1655(树形dp))

    poj 1655:http://poj.org/problem?id=1655 题意: 给无根树,  找出以一节点为根,  使节点最多的树,节点最少. 题解:一道树形dp,先dfs 标记 所有节点的子 ...

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

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

  4. poj 1741 Tree (树的分治)

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

  5. poj 1744 tree 树分治

    Tree Time Limit: 1000MS   Memory Limit: 30000K       Description Give a tree with n vertices,each ed ...

  6. [codeforces161D]Distance in Tree(点分治/树形dp)

    题意:求树上距离为k的点对个数: 解题关键:练习一下点分治不用容斥 而直接做的做法.注意先查询,后更新. 不过这个方法有个缺陷,每次以一个新节点为根,必须memset mp数组,或许使用map会好些, ...

  7. POJ 1741 Tree ——点分治

    [题目分析] 这貌似是做过第三道以Tree命名的题目了. 听说树分治的代码都很长,一直吓得不敢写,有生之年终于切掉这题. 点分治模板题目.自己YY了好久才写出来. 然后1A了,开心o(* ̄▽ ̄*)ブ ...

  8. 『You Are Given a Tree 整体分治 树形dp』

    You Are Given a Tree Description A tree is an undirected graph with exactly one simple path between ...

  9. Tree POJ - 1741【树分治】【一句话说清思路】

    因为该博客的两位作者瞎几把乱吹(" ̄︶ ̄)人( ̄︶ ̄")用彼此的智慧总结出了两条全新的定理(高度复杂度定理.特异根特异树定理),转载请务必说明出处.(逃 Pass:anuonei, ...

随机推荐

  1. Delphi LiveBinds组件

    Component Logo Component Name Description TBindSourceDB Is used for creating bindings to databases. ...

  2. 秒懂,Java 注解 (Annotation)你可以这样学 - CSDN博客

    https://blog.csdn.net/briblue/article/details/73824058 文章开头先引入一处图片. 这处图片引自老罗的博客.为了避免不必要的麻烦,首先声明我个人比较 ...

  3. Python模块hashlib

    Python的hashlib提供了常见的摘要算法,如MD5,SHA1等等. 什么是摘要算法呢?摘要算法又称哈希算法.散列算法.它通过一个函数,把任意长度的数据转换为一个长度固定的数据串(通常用16进制 ...

  4. 正点原子stm32f103mini版串口下载BOOT0引脚与与CH340G芯片引脚RTS、DTR、的关系原理

    在做串口实验时,一直搞不明白一键下载是怎么回事,于是自己就去捉摸CH340G这块芯片,那么这里我将详细的讲解一下这块芯片怎么与stm32配合使用的. 1.由CH340G芯片资料可以知道这两个引脚的功能 ...

  5. 【剑指offer】数组中只出现一次的数字

    题目:一个整型数组里除了两个数字之外,其他的数字都出现了偶数次.请写程序找出这两个只出现一次的数字. 思路1:使用HashMap存上所有的数字,数字作为Key,Value为对应的出现次数.这种做法可以 ...

  6. 【剑指offer】求树中满足和为给定数字的路径

    题目: 输入一颗二叉树的跟节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径.路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径.(注意: 在返回值的list中,数组长度大的 ...

  7. CLOSE_WAIT状态的原因与解决方法

    https://blog.csdn.net/Windgs_YF/article/details/83513696 netstat -nat|awk '{print $6}'|sort|uniq -c| ...

  8. x86 asm调用框架(vs2015)

    EXTERN_C void _stdcall Asm_1();//在cpp文件下 要使用EXTERN_C . .MODEL FLAT,C,stdcall .DATA .CODE Asm_1 PROC ...

  9. sql使用实例

    将另一表中的合计值保存到指定字段,并将空值赋0 update ShopInfo set JLRunningWater =(select COALESCE(sum(v.TotalMoney),0) as ...

  10. JAVA使用log4j(另SSM框架中使用log4j)

    1.引入jar包 log4j-1.2.13.jar 2.src下建立配置文件:log4j.properties #不+All,只写后一种LOG log4j.rootLogger =ALL,system ...