跟着机房的潮流学了点分治,发现这个东西其实还蛮好写的,学会思想,很容易YY出来。直接上习题。
POJ 1741 TREE
点分治的模板题,首先设点x到当前子树跟root的距离为gx,则满足gx+gy≤k可以加进答案,但是注意如果x,y在同一棵子树中,就要删去对答案的贡献,以为x,y会在其所在的子树中在计算一次。注意无根树转有根树的过程,需要选取树的重心防止复杂度从O(nlog2n)退化为O(n2) code:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define inf 100000
using namespace std;
struct hp{
int u,v,w;
}a[20001];
struct hq{
int size;
}tree[10001];
bool done[10001];
int point[10001],next[20001];
int len[10001];
int n,m,e=0,t=0;
int size,root,sizenow,tot,ans=0;
void add(int u,int v,int w)
{
e++; a[e].u=u; a[e].v=v; a[e].w=w; next[e]=point[u]; point[u]=e;
e++; a[e].u=v; a[e].v=u; a[e].w=w; next[e]=point[v]; point[v]=e;
}
void findsize(int now,int last)
{
int i,tmp=0;
sizenow++;
for (i=point[now];i;i=next[i])
if (a[i].v!=last&&!done[a[i].v])
findsize(a[i].v,now);
}
void findroot(int now,int last)
{
int i,tmp=0;
tree[now].size=1; tmp=0;
for (i=point[now];i;i=next[i])
if (a[i].v!=last&&!done[a[i].v])
{
findroot(a[i].v,now);
tree[now].size+=tree[a[i].v].size;
if (tree[a[i].v].size>tmp)
tmp=tree[a[i].v].size;
}
if (sizenow-tree[now].size>tmp) tmp=sizenow-tree[now].size;
if (tmp<size)
{root=now; size=tmp;}
}
void findroad(int now,int last,int road)
{
int i,tmp=0;
len[++t]=road;
if (road>m) return;
for (i=point[now];i;i=next[i])
if (a[i].v!=last&&!done[a[i].v])
findroad(a[i].v,now,road+a[i].w);
}
int calc(int k)
{
int i,l,r,ret=0;
sort(len+1,len+t+1);
for (l=1,r=t;l<r;)
{
if (len[l]+len[r]<=k) ret+=r-l++;
else r--;
}
return ret;
}
void work(int now)
{
int i;
sizenow=0; t=0; size=inf;
findsize(now,0);
findroot(now,0);
findroad(root,0,0);
done[root]=true;
ans+=calc(m);
for (i=point[root];i;i=next[i])
if (!done[a[i].v])
{
t=0; sizenow=0; size=inf;
findroad(a[i].v,0,0);
ans-=calc(m-2*a[i].w);
findsize(a[i].v,0);
findroot(a[i].v,0);
work(a[i].v);
}
}
int main()
{
int i,x,y,z;
scanf("%d%d",&n,&m);
while (n!=0&&m!=0)
{
e=0; ans=0;
memset(point,0,sizeof(point));
memset(done,false,sizeof(done));
for (i=1;i<=n-1;++i)
{
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
}
work(1);
printf("%d\n",ans);
scanf("%d%d",&n,&m);
}
}
时间: 2024-10-10 20:54:10