待更新
Description
给出一棵带边权的树,问有多少对点的距离<=Len
c表示最大儿子的节点的size
size表示子树大小
处理子树大小
void Get_Size(int x,int y)
{
size[x]=1;
c[x]=0;
for (int k=last[x];k;k=next[k])
{
if (t[k]==y || bz[t[k]]) continue;
Get_Size(t[k],x);
size[x]+=size[t[k]];
c[x]=max(c[x],size[t[k]]);
}
}
找重心
//size[r]-size[x]是x上面部分的树的尺寸,跟x的最大孩子比,找到最大孩子的最小差值节点
void Get_Root(int r,int x,int y)
{
c[x]=max(c[x],size[r]-size[x]);
if (c[x]<Max) Max=c[x],root=x;
for (int k=last[x];k;k=next[k])
{
if (t[k]==y || bz[t[k]]) continue;
Get_Root(r,t[k],x);
}
}
求每个点离重心的距离
void Get_Dis(int x,int sum,int y)
{
dis[++num]=sum;
for (int k=last[x];k;k=next[k])
{
if (t[k]!=y && !bz[t[k]])
Get_Dis(t[k],sum+val[k],x);
}
}
计算以x为根的子树中有多少点对的距离小于等于len
int Calc(int x,int sum)
{
int Res=0;
num=0;
Get_Dis(x,sum,0);
sort(dis+1,dis+num+1);
int i=0,j=num;
while (i<j)
{
i++;
while (dis[i]+dis[j]>len && i<j) j--;
Res+=j-i;
}
return Res;
}
大肥水
void Dfs(int x)
{
Max=n;
Get_Size(x,0);
Get_Root(x,x,0);
ans+=Calc(root,0);
bz[root]=true;
for (int k=last[root];k;k=next[k])
{
if (!bz[t[k]])
{
ans-=Calc(t[k],val[k]);
Dfs(t[k]);
}
}
}
CODE
#include <cstdio>
#include <iostream>
#include <algorithm>
#define fo(i,a,b) for (int i=a;i<=b;i++)
#define N 10005
using namespace std;
int n,len,l=0,ans=0,Max=0,root=0;
int t[N*2],last[N],next[N*2],val[N*2],size[N],c[N],dis[N],num=0;
bool bz[N];
void add(int x,int y,int z)
{
t[++l]=y;
next[l]=last[x];
last[x]=l;
val[l]=z;
}
void Get_Size(int x,int y)
{
size[x]=1;
c[x]=0;
for (int k=last[x];k;k=next[k])
{
if (t[k]==y || bz[t[k]]) continue;
Get_Size(t[k],x);
size[x]+=size[t[k]];
c[x]=max(c[x],size[t[k]]);
}
}
void Get_Root(int r,int x,int y)
{
c[x]=max(c[x],size[r]-size[x]);
if (c[x]<Max) Max=c[x],root=x;
for (int k=last[x];k;k=next[k])
{
if (t[k]==y || bz[t[k]]) continue;
Get_Root(r,t[k],x);
}
}
void Get_Dis(int x,int sum,int y)
{
dis[++num]=sum;
for (int k=last[x];k;k=next[k])
{
if (t[k]!=y && !bz[t[k]])
Get_Dis(t[k],sum+val[k],x);
}
}
int Calc(int x,int sum)
{
int Res=0;
num=0;
Get_Dis(x,sum,0);
sort(dis+1,dis+num+1);
int i=0,j=num;
while (i<j)
{
i++;
while (dis[i]+dis[j]>len && i<j) j--;
Res+=j-i;
}
return Res;
}
void Dfs(int x)
{
Max=n;
Get_Size(x,0);
Get_Root(x,x,0);
ans+=Calc(root,0);
bz[root]=true;
for (int k=last[root];k;k=next[k])
{
if (!bz[t[k]])
{
ans-=Calc(t[k],val[k]);
Dfs(t[k]);
}
}
}
int main()
{
scanf("%d%d",&n,&len);
fo(i,1,n-1)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
add(y,x,z);
}
Dfs(1);
printf("%d\n",ans);
return 0;
}