去年这个时候就做这道题了 那个时候完全不懂
今天重新来学了一下点分治 发现自己很多不会
没有照着别人的程序打点分治的时候思路很乱 可能是自己太弱了
后来看了黄学长的代码发现有些东西我打的太复杂了。。。。
然后我就像到了一个新世界
每次都去找中心就好了。。。。
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
char c;
bool flag;
inline void read(int &a)
{
a=0,flag=false;do c=getchar();while(c!='-'&&(c<'0'||c>'9'));
if(c=='-')flag=true,c=getchar();
while(c<='9'&&c>='0')a=(a<<3)+(a<<1)+c-'0',c=getchar();
if(flag)a=-a;
}
int root;
struct Chain{Chain *next;int u,len;Chain(){next=NULL;}}*Head[100001];
bool choose[10001];
int sum;
int Max[100001],son[100001];
void Get_Root(int u,int fa)
{
son[u]=1;
Max[u]=0;
for(Chain *tp=Head[u];tp;tp=tp->next)
{
if(tp->u==fa||choose[tp->u])continue;
Get_Root(tp->u,u);
son[u]+=son[tp->u];
Max[u]=max(Max[u],son[tp->u]);
}
Max[u]=max(Max[u],sum-son[u]);
if(Max[u]<Max[root])root=u;
}
int deep[100001];
inline void addside(int a,int b,int len)
{ Chain *tp=new Chain;
tp->u=b,tp->len=len,tp->next=Head[a];
Head[a]=tp;
swap(a,b);
tp=new Chain;
tp->u=b,tp->len=len,tp->next=Head[a];
Head[a]=tp;
}
int D[100001];
inline void De(int u,int fa)
{
for(Chain *tp=Head[u];tp;tp=tp->next)
if(tp->u!=fa&&!choose[tp->u])
D[tp->u]=D[u]+tp->len,deep[++deep[0]]=D[tp->u],De(tp->u,u);
}
int k;
int Sol_dep(int u,int delta)
{
int res=0;
deep[0]=0;
D[u]=deep[++deep[0]]=delta;
De(u,u);
sort(deep+1,deep[0]+deep+1);
int l=1,r=deep[0];
while(l<r)
{
if(deep[l]+deep[r]>k)
r--;
else res+=r-l,l++;
}
return res;
}
int ans;
int Div(int u)
{
ans+=Sol_dep(u,0);
choose[u]=true;
for(Chain *tp=Head[u];tp;tp=tp->next)
{
if(choose[tp->u])continue;
ans-=Sol_dep(tp->u,tp->len);
sum=son[tp->u];
root=0;
Get_Root(tp->u,root);
Div(root);
}
}
int main()
{
int a,b,c;
while(true)
{
int n;
read(n),read(k);
memset(choose,false,sizeof(choose));
if(!n)return 0;
for(int i=1;i<=n;i++)
Head[i]=NULL;
for(int i=1;i<n;i++)
{
read(a),read(b),read(c),addside(a,b,c);
}
sum=n;root=0;
Max[0]=1<<29;
ans=0;
Get_Root(1,0);
Div(root);
printf("%d\n",ans);
}
return 0;
}