/*
不要低头,不要放弃,不要气馁,不要慌张
题意:
给一棵有n个节点的树,每条边都有一个正权值,求一共有多少个点对使得它们之间路的权值和小于给定的k.
思路:
《分治算法在树的路径问题中的应用》
*/ #include<stdio.h>
#include<vector>
#include<string.h>
#include<algorithm>
#define N 10050
using namespace std;
struct edge{
int id;
long long w;
bool im;
edge *next;
};
struct st{
st(){}
st(int a,long long b,int c){
id=a;dis=b;iid=c;
}
int id,iid;
long long dis;
};
vector<st>mv;
edge edges[N*];
edge *adj[N];
long long ans,kk;
int ednum;
inline void addedge(int a,int b,long long c){
edge *tmp=&edges[ednum++];
tmp->id=b;
tmp->w=c;
tmp->im=;
tmp->next=adj[a];
adj[a]=tmp;
}
int zong,next_val,next;
bool vis[N];
int siz[N],fa[N];
long long dis[N];
void dfs(int pos,int dep){
vis[pos]=;
siz[pos]=;
for(edge *it=adj[pos];it;it=it->next){
if(it->im&&!vis[it->id]){
dfs(it->id,dep+);
siz[pos]+=siz[it->id];
}
}
}
void dfs2(int pos,int dep){
int my_next=-;
vis[pos]=;
for(edge *it=adj[pos];it;it=it->next){
if(it->im&&!vis[it->id]){
my_next=max(my_next,siz[it->id]);
}
}
my_next=max(my_next,zong-siz[pos]);
if(next_val>my_next){
next=pos;
next_val=my_next;
}
for(edge *it=adj[pos];it;it=it->next){
if(it->im&&!vis[it->id]){
dfs2(it->id,dep+);
}
}
}
bool cmp1(st a,st b){
if(a.dis!=b.dis)return a.dis<b.dis;
else return a.iid<b.iid;
}
bool cmp2(st a,st b){
if(a.id!=b.id)return a.id<b.id;
else if(a.dis!=b.dis)return a.dis<b.dis;
else return a.iid<b.iid;
}
inline void del(int a,int b){
for(edge *it=adj[a];it;it=it->next){
if(it->id==b){
it->im=;
return;
}
}
}
void dfs3(int pos,int dep){
vis[pos]=;
if(!dep)dis[pos]=;
for(edge *it=adj[pos];it;it=it->next){
if(it->im&&!vis[it->id]){
if(!dep)fa[it->id]=it->id;
else fa[it->id]=fa[pos];
dis[it->id]=dis[pos]+it->w;
mv.push_back(st(fa[it->id],dis[it->id],it->id));
dfs3(it->id,dep+);
}
}
}
void solve(int pos){
mv.clear();
memset(vis,,sizeof(vis));
dfs(pos,);
zong=siz[pos];
if(zong<=)return;
memset(vis,,sizeof(vis));
next_val=;
dfs2(pos,);
memset(vis,,sizeof(vis));
dfs3(next,);
int n=mv.size();
sort(mv.begin(),mv.end(),cmp1);
for(int i=;i<n;i++){
if(mv[i].dis>kk)break;
ans++;
int l=i+,r=n-;
while(l<=r){
int mid=(l+r)>>;
if(mv[i].dis+mv[mid].dis<=kk)l=mid+;
else r=mid-;
}
ans+=r-i;
}
sort(mv.begin(),mv.end(),cmp2);
int st=;
for(int i=;i<n;i++){
if(mv[i].id!=mv[st].id){
for(int j=st;j<i;j++){
int l=j+,r=i-;
while(l<=r){
int mid=(l+r)>>;
if(mv[j].dis+mv[mid].dis<=kk)l=mid+;
else r=mid-;
}
ans-=r-j;
}
st=i;
}
}
for(int j=st;j<n;j++){
int l=j+,r=n-;
while(l<=r){
int mid=(l+r)>>;
if(mv[j].dis+mv[mid].dis<=kk)l=mid+;
else r=mid-;
}
ans-=r-j;
}
vector<int>mmv;
for(edge *it=adj[next];it;it=it->next){
if(it->im&&siz[it->id]>){
mmv.push_back(it->id);
it->im=;
del(it->id,next);
}
}
for(int i=;i<mmv.size();i++)solve(mmv[i]);
}
int main()
{
int n;
while(scanf("%d%lld",&n,&kk)!=EOF){
ans=;
if(!n)break;
memset(adj,NULL,sizeof(adj));
ednum=;
for(int i=;i<n;i++){
int a,b;
long long c;
scanf("%d%d%lld",&a,&b,&c);
addedge(a,b,c);
addedge(b,a,c);
}
solve();
printf("%lld\n",ans);
}
}

POJ 1741 [点分治][树上路径问题]的更多相关文章

  1. POJ 1741 Tree 求树上路径小于k的点对个数)

                                                                                                 POJ 174 ...

  2. POJ 1741 树分治

    题目链接[http://poj.org/problem?id=1741] 题意: 给出一颗树,然后寻找点对(u,v)&&dis[u][v] < k的对数. 题解: 这是一个很经典 ...

  3. [八分之三的男人] POJ - 1741 点分治 && 点分治笔记

    题意:给出一棵带边权树,询问有多少点对的距离小于等于\(k\) 本题解参考lyd的算法竞赛进阶指南,讲解的十分清晰,比网上那些讲的乱七八糟的好多了 不过写起来还是困难重重(史诗巨作 打完多校更详细做法 ...

  4. POJ 1741 点分治

    方法:指针扫描数组 每次选择树的重心作为树根,从树根出发进行一次DFS,求出点到树根的距离,把节点按照与树根的的距离放进数组d,设置两个指针L,R分别从前.后开始扫描,每次满足条件时答案累加R-L., ...

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

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

  6. poj 1741 楼教主男人八题之中的一个:树分治

    http://poj.org/problem? id=1741 Description Give a tree with n vertices,each edge has a length(posit ...

  7. POJ 1741.Tree and 洛谷 P4178 Tree-树分治(点分治,容斥版) +二分 模板题-区间点对最短距离<=K的点对数量

    POJ 1741. Tree Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 34141   Accepted: 11420 ...

  8. 点分治——POJ 1741

    写的第一道点分治的题目,权当认识点分治了. 点分治,就是对每条过某个点的路径进行考虑,若路径不经过此点,则可以对其子树进行考虑. 具体可以看menci的blog:点分治 来看一道例题:POJ 1741 ...

  9. poj 1741 树的点分治(入门)

    Tree Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 18205   Accepted: 5951 Description ...

随机推荐

  1. windows 下面安装npm

    npm(简称:Node Packaged Modules)是nodejs官方未nodejs定制的一个工具,是Node.js的包管理器,通过npm可以下载安装nodejs的模块包,nodejs有很多优秀 ...

  2. jquery里面的循环的用法

    下面提一下jQuery的each方法的几种常用的用法 Js代码 var arr = [ "one", "two", "three", &qu ...

  3. 第五章——搭建S3C6410开发板的测试环境

    搭建S3C6410开发板的测试环境 通过本章的学习学会了如何在开发板上安装Android.开发板是学习和开发嵌入式技术的主要硬件设备,想要顺利的通过linux驱动访问硬件,是不能在PC板上模拟的,需要 ...

  4. 今天网站后台登录页面需要生成一个二维码,然后在手机app上扫描这个二维码,实现网站登录的效果及其解决方案如下

    要实现二维码登录,需要解决2个技术,1.需要js websocket 与后台php实现长连接技术 2.实现二维码生成技术 要实现这个功能第二个算是比较简单,只需要下载一个php的二维码生成器即可,但要 ...

  5. 《C专家编程》第三章——分析C语言的声明

    前面一章我们已经说过C语言存在的一些问题和它晦涩的地方,让我们对这门神奇的语言有了更深的了解.现在这一章则集中精力来讨论C语言的声明,分为三块,首先是说明C语言声明晦涩难懂的原因和声明是如何形成的,其 ...

  6. 将jar包直接Buldpath所引起的问题

    今天在学习jasperReports时遇到个很郁闷的问题,发现自己的jar包通过Buildpath导进去后,一运行,出现了一些错误. 找不到类 这就很尴尬了,我已经按要求都导进去了,竟然提示我找不到类 ...

  7. assign、copy 、retain等关键字的含义

    assign: 简单赋值,不更改索引计数copy: 建立一个索引计数为1的对象,然后释放旧对象retain:释放旧的对象,将旧对象的值赋予输入对象,再提高输入对象的索引计数为1Copy其实是建立了一个 ...

  8. Android ui 测试课堂笔记

    开始接触Android ui测试了,笔记如下 模拟器 Genemotion , the fastest android simulator in the world Android ui 测试工具 S ...

  9. VS2008编译bat

    工程文件为AirCode,批处理文件为bulit.bat(与*.sln文件在同级目录). 以下是批处理的代码: echo %~dp0 rem set build_config="Debug| ...

  10. Python底层socket库

    Python底层socket库将Unix关于网络通信的系统调用对象化处理,是底层函数的高级封装,socket()函数返回一个套接字,它的方法实现了各种套接字系统调用.read与write与Python ...