/*
不要低头,不要放弃,不要气馁,不要慌张
题意:
给一棵有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. (原创)VM中的CentOS6.4中安装CloudStack6.3②

    接着VM中的CentOS6.4中安装CloudStack6.3①中文章接着,往下面安装 4.更新 yum 仓库 默认情况下,CentOS的软件源中没有收录最新版本CloudStack,为了能顺利安装, ...

  2. mvn打包时添加version和profile

    <!-- 定义profile --> <profiles> <!-- 开发环境 --> <profile> <id>dev</id&g ...

  3. 移动端头像上传AJax input file

    jQuery中的Ajax不能支持 input file 需要用ajaxupload.js但是先需要引入jQuery文件 <script src="__PUBLIC__/js/ajaxf ...

  4. Matlab编程基础

    平台:Win7 64 bit,Matlab R2014a(8.3) “Matlab”是“Matrix Laboratory” 的缩写,中文“矩阵实验室”,是强大的数学工具.本文侧重于Matlab的编程 ...

  5. 20160405互联网新闻<来自涛涛大产品>

    1.滴滴或将收购腾讯地图,打造“滴滴地图”(滴滴与神州.uber之间的争斗,归根到底还是BAT的代理人之战)2.优信二手车否认合并传言 并谴责58同城仿冒优信网站(商战无所不用其极)3.京东旗下的拍拍 ...

  6. 深入剖析ConcurrentHashMap(1)

    转载自并发编程网 – ifeve.com本文链接地址: 深入剖析ConcurrentHashMap(1) ConcurrentHashMap是Java5中新增加的一个线程安全的Map集合,可以用来替代 ...

  7. jquery .attr()

    在JS中设置节点的属性与属性值用到setAttribute(),获得节点的属性与属性值用到getAttribute(),而在jquery中,用一个attr()就可以全部搞定了,赞一个先 ^^ jque ...

  8. MySql和Oracle的日期转换到底有哪些不同?我们来比较一下

    1.MySql和Oracle的日期转换 mysql中有2种日期格式DATE和TIME,oracle只有一种日期格式DATE. oracle> select to_char(sysdate,'yy ...

  9. iOS开发之cell多按钮

    iOS开发经常出现cell需要多个按钮,一般以为要导入第三方框架.但其实iOS 8以后,系统提供了UITableViewRowAction以及新的delegate方法,使得自定义一些操作变得非常容易. ...

  10. 11.12模拟考T2(GCD)

    2.梅花桩   (blossom.pas/c/cpp) [问题描述] 小x在练习一门轻功,这门轻功是在梅花桩上跳来跳去,这门轻功是严格按照直线从一个梅花桩直接跳到另外一个梅花桩上.因为小x有恐高症,所 ...