Tree
Time Limit: 1000MS   Memory Limit: 30000K
Total Submissions: 15548   Accepted: 5054

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

【思路】

设i到当前root的距离为d[i],i属于belong[i]->belong[i]为当前root的儿子且i在belong[i]为根的树中。设Sum{E}为满足条件E的点对数。

情况分为两种:

    1)      经过根节点

    2)      不经过根节点,在根节点的一颗子树中。

   其中2)可以递归求解。

   对于1)我们要求的是Sum{d[i]+d[j]<=k && belong[i]!=belong[j]},即为

   Sum{d[i]+d[j]<=k}  -  Sum{ d[i]+d[j]<=k && belong[i]==belong[j]}

前后两项都可以转化为求一个序列a中满足d[a[i]]+d[a[j]]<=k的点对数。

先将a按照d值排序,基于单调性,我们可以给出一个O(n)的统计方法。于是问题得到解决。

总的时间复杂度为O(nlog2n)

【代码】

 #include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std; const int N = +;
const int INF = 1e9; struct Edge{
int u,v,w;
Edge(int u=,int v=,int w=):u(u),v(v),w(w){};
};
int n,K,l1,l2,tl,ans;
int siz[N],d[N],list[N],f[N],can[N];
vector<Edge> es;
vector<int> g[N];
void adde(int u,int v,int w) {
es.push_back(Edge(u,v,w));
int m=es.size(); g[u].push_back(m-);
} void init() {
ans=; es.clear();
memset(can,,sizeof(can));
for(int i=;i<=n;i++) g[i].clear();
}
void dfs1(int u,int fa) {
siz[u]=;
list[++tl]=u;
for(int i=;i<g[u].size();i++) {
int v=es[g[u][i]].v;
if(v!=fa && can[v]) {
dfs1(v,u);
f[v]=u; siz[u]+=siz[v];
}
}
}
int getroot(int u,int fa) { //寻找u子树重心
int pos,mn=INF;
tl=;
dfs1(u,fa);
for(int i=;i<=tl;i++) {
int y=list[i],d=;
for(int j=;j<g[y].size();j++) {
int v=es[g[y][j]].v;
if(v!=f[y] && can[v]) d=max(d,siz[v]);
}
if(y!=u) d=max(d,siz[u]-siz[y]); //上方
if(d<mn) mn=d , pos=y; //使大子结点数最小
}
return pos;
}
void dfs2(int u,int fa,int dis) {
list[++l1]=u; d[u]=dis;
for(int i=;i<g[u].size();i++) {
int v=es[g[u][i]].v;
if(v!=fa && can[v]) dfs2(v,u,dis+es[g[u][i]].w);
}
}
int getans(int* a,int l,int r) {
int res=,j=r;
for(int i=l;i<=r;i++) {
while(d[a[i]]+d[a[j]]>K && j>i) j--;
res+=j-i; if(i==j) break;
}
return res;
}
bool cmp(const int& x,const int& y) { return d[x]<d[y]; }
void solve(int u,int fa) {
int root=getroot(u,fa);
l1=l2=;
for(int i=;i<g[root].size();i++) { //统计 d[i]+d[j]<=K && belong[i]==belong[j]
int v=es[g[root][i]].v;
if(can[v]) {
l2=l1;
dfs2(v,root,es[g[root][i]].w); //insert[以v为根的子树]
sort(list+l2+,list+l1+,cmp);
ans-=getans(list,l2+,l1);
}
}
list[++l1]=root; d[root]=can[root]=;
sort(list+,list+l1+,cmp);
ans+=getans(list,,l1); //统计d[i]+d[j]<=K
for(int i=;i<g[root].size();i++) { //递归<-分治
int v=es[g[root][i]].v;
if(v!=fa && can[v]) solve(v,root);
}
} int main() {
while(scanf("%d%d",&n,&K)== && (n&&K)) {
int u,v,w;
init();
for(int i=;i<n-;i++) {
scanf("%d%d%d",&u,&v,&w);
adde(u,v,w) , adde(v,u,w);
}
solve(,-);
printf("%d\n",ans);
}
return ;
}

最新文章

  1. [Modern OpenGL系列(四)]在OpenGL中使用Shader
  2. shell 脚本之循环使用 for while 详解
  3. 轮播插件unsilder 源码解析(一)---使用
  4. workman源代码阅读 - 使用信号处理器实现定时器
  5. --自动创建备份SQL
  6. [转]save all TWebbrowser Frame Sources?
  7. 禁止从别的应用启动Activity
  8. INSERT INTO 语句的语法错误【 OLE报错,office终端执行SQL没有问题】
  9. ABP的第一个程序和遇到的一些问题
  10. 网上搜集了点资料,学web的人互相分享共同进步吧(php编码的好习惯必须养成)
  11. I am back
  12. 验证页面多个input文本的必填项
  13. linux 下文件节点索引
  14. LR中日志设置和日志函数
  15. JavaScript 闭包详解
  16. 浏览器信息(Navigator)
  17. win7下设置 WiFi AP
  18. hdu2534-Score
  19. 自定义工作流活动报错:您无法登陆系统。原因可能是您的用户记录或您所属的业务部门在Microsoft Dynamics 365中已被禁用。
  20. python开发:python字符串操作方法

热门文章

  1. 6779. Can you answer these queries VII - SPOJ
  2. sql不重复的查找统计数据(经典)
  3. win8系统中PL/SQL Developer连接Oracle出现的问题
  4. TaskTracker执行map或reduce任务的过程(二)
  5. hdu 1851 A Simple Game 博弈论
  6. Java的ResultSet中rs.next()含义
  7. MAC OS Nginx php-fpm相关
  8. JMS基础(2)
  9. Vim的撤销与重做
  10. brew,gem,rvm 和 bundler软件包的管理工具