题目:Tree
解析:
上一次做点分治已经是半年前了。。。
所以点分治其实就是一种树上分治,序列上的分治是取中点,而点分治是取重心,就这么点区别。至于为什么取重心,这样能保证复杂度在
O
(
l
o
g
N
)
O(logN)
O(logN)级别。
对于这道题的具体做法,先找出重心,计算经过重心且两端点不在同一棵子树中的合法路径,具体做法可以把每个点按照离重心的距离排序,用两个指针
L
,
R
L,R
L,R分别从前,后扫描,容易发现
L
L
L在从左往右扫描时
R
R
R时递减的,这样不会算漏。但是可能会算重,即两点在同一棵子树内,这时当递归处理子树时减去这种情况即可,详见代码,所以最终算法过程:
1. 寻找当前重心
p
p
p。
2.从从
p
p
p开始
D
F
S
DFS
DFS,求出每个点到重心的距离。
3.累加答案。
4.删除重心(具体操作就是标记重心为访问过),递归计算子树。
代码:
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
const int Max=10010;
int n,m,s,rt,tot,sum,ans,k;
int first[Max],size[Max],d[Max],dep[Max],vis[Max],dis[Max];
struct shu{int to,next,len;}e[Max<<1];
inline int get_int()
{
int x=0,f=1;char c;
for(c=getchar();(!isdigit(c))&&(c!='-');c=getchar());
if(c=='-') f=-1,c=getchar();
for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';
return x*f;
}
inline void print(int x)
{
if(x>9) print(x/10);
putchar('0'+x%10);
}
inline void clean()
{
s=ans=0;
memset(first,0,sizeof(first));
memset(vis,0,sizeof(vis));
}
inline void build(int x,int y,int z)
{
e[++s].next=first[x],first[x]=s,e[s].to=y,e[s].len=z;
e[++s].next=first[y],first[y]=s,e[s].to=x,e[s].len=z;
}
inline void getp(int p,int fa)
{
size[p]=1;int maxx=0;
for(int u=first[p];u;u=e[u].next)
{
int to=e[u].to;
if(vis[to]||to==fa) continue;
getp(to,p),size[p]+=size[to],maxx=max(maxx,size[to]);
}
maxx=max(maxx,sum-size[p]);
if(maxx<m) m=maxx,rt=p;
}
inline void getd(int p,int fa)
{
dis[++tot]=d[p];
for(int u=first[p];u;u=e[u].next)
{
int to=e[u].to;
if(to==fa||vis[to]) continue;
d[to]=d[p]+e[u].len,getd(to,p);
}
}
inline int calc(int p,int q)
{
tot=0,d[p]=q,getd(p,0);
sort(dis+1,dis+tot+1);
int l=1,r=tot,x=0;
while(l<r)
{
if(dis[l]+dis[r]>k) r--;
else x+=r-l,l++;
}
return x;
}
inline void dfs(int p)
{
ans+=calc(p,0),vis[p]=1;
for(int u=first[p];u;u=e[u].next)
{
int to=e[u].to;
if(vis[to]) continue;
ans-=calc(to,e[u].len);
m=1e9,sum=size[to],getp(to,rt),dfs(rt);
}
}
inline void init()
{
while(1)
{
n=get_int(),k=get_int();
if(!n&&!k) break;
clean();
for(int i=1;i<n;i++)
{
int x=get_int(),y=get_int(),z=get_int();
build(x,y,z);
}
m=1e9,sum=n,getp(1,0),dfs(rt);
print(ans),putchar('\n');
}
}
int main()
{
init();
return 0;
}