标签:code math sort 大小 alc line continue n+1 容斥
点分治用来处理树上路径问题,每一次将树分治为几棵子树,然后继续递归,得到答案
每次分治时,子树的根选取为其的重心,递归的子树大小不会超过原树大小的一半,保证了时间复杂度为\(O(n\ log\ n)\)
利用容斥原理统计答案
树上有多少对点,满足两点间的距离小于等于\(k\)
\(code:\)
void dfs_root(int x,int fa)
{
siz[x]=1,ma[x]=0;
for(int i=head[x];i;i=e[i].nxt)
{
int y=e[i].to;
if(vis[y]||y==fa) continue;
dfs_root(y,x);
siz[x]+=siz[y];
ma[x]=max(ma[x],siz[y]);
}
ma[x]=max(ma[x],tot-siz[x]);
if(ma[x]<ma[root]) root=x;
}
void dfs_dis(int x,int fa)
{
len[++len_cnt]=dis[x];
for(int i=head[x];i;i=e[i].nxt)
{
int y=e[i].to,v=e[i].v;
if(vis[y]||y==fa) continue;
dis[y]=dis[x]+v;
dfs_dis(y,x);
}
}
int calc(int x,int lenth)
{
len_cnt=0;
dis[x]=lenth;
dfs_dis(x,0);
sort(len+1,len+len_cnt+1);
int sum=0,l=1,r=len_cnt;
while(l<r)
{
if(len[l]+len[r]<=k) sum+=r-l,l++;
else r--;
}
return sum;
}
void solve(int x)
{
vis[x]=true;
ans+=calc(x,0);
for(int i=head[x];i;i=e[i].nxt)
{
int y=e[i].to,v=e[i].v;
if(vis[y]) continue;
ans-=calc(y,v);
root=0,tot=siz[x];
dfs_root(y,0);
solve(root);
}
}
标签:code math sort 大小 alc line continue n+1 容斥
原文地址:https://www.cnblogs.com/lhm-/p/12229531.html