解法論文中有,就是把路徑分成經過樹根,和不經過樹根兩類,每次處理經過樹根的,然後剩下的子樹部分可以遞歸處理,如果每次選取樹的重心,那麼可以保證最多遞歸logn層。經過樹根的先排序,然後O(n)的復雜度就能算出,那麼每層的復雜度nlogn,最多遞歸logn層,總復雜度nlogn^2
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=1e4+9;
int head[maxn],lon;
bool use[maxn];
int a[maxn],d[maxn],top,son[maxn];
int ans,n,m,mm;
struct
{
int next,to,w;
}e[maxn<<1];
void edgeini()
{
memset(head,-1,sizeof(head));
lon=-1;
}
void edgemake(int from,int to,int w)
{
e[++lon].to=to;
e[lon].w=w;
e[lon].next=head[from];
head[from]=lon;
}
int maxson[maxn];
int dp(int t,int from)
{
int now,tmp=1e5,ans;
son[t]=maxson[t]=0;
for(int k=head[t];k!=-1;k=e[k].next)
{
int u=e[k].to;
if(use[u]||u==from) continue;
now=dp(u,t);
if(maxson[now]<tmp)
{
tmp=maxson[now];
ans=now;
}
son[t]+=son[u];
maxson[t]=max(maxson[t],son[u]);
}
son[t]++;
maxson[t]=max(maxson[t],mm-son[t]);
if(maxson[t]<tmp) ans=t;
return ans;
}
void dfs(int t,int from)
{
a[++top]=d[t];
son[t]=0;
for(int k=head[t],u;k!=-1;k=e[k].next)
{
u=e[k].to;
if(use[u]||u==from) continue;
d[u]=d[t]+e[k].w;
dfs(u,t);
son[t]+=son[u];
}
son[t]++;
}
int cal(int l,int r)
{
int ret=0,now=r;
for(int i=l;i<=now;i++)
{
while(now>i&&a[i]+a[now]>m) now--;
ret+=now-i;
}
return ret;
}
void solve(int t)
{
int now=dp(t,0);
d[now]=top=0;
use[now]=1;
dfs(now,0);
int ret=0,tmp=2;
for(int k=head[now];k!=-1;k=e[k].next)
{
int u=e[k].to;
if(use[u]) continue;
sort(a+tmp,a+tmp+son[u]);
ret+=cal(tmp,tmp+son[u]-1);
tmp+=son[u];
}
sort(a+1,a+tmp);
ans+=cal(1,tmp-1)-ret;
// printf("%d %d\n",now,ans);
for(int k=head[now];k!=-1;k=e[k].next)
{
int u=e[k].to;
if(use[u]||son[u]==1) continue;
mm=son[u];
solve(u);
}
}
int main()
{
// freopen("in.txt","r",stdin);
while(scanf("%d %d",&n,&m),n&&m)
{
edgeini();
for(int i=1,from,to,w;i<n;i++)
{
scanf("%d %d %d",&from,&to,&w);
edgemake(from,to,w);
edgemake(to,from,w);
}
memset(use,0,sizeof(use));
ans=0;
mm=n;
solve(1);
cout<<ans<<endl;
}
return 0;
}