点分治,就是在树上分治,讲得很高大上。。。。。。。。
实际上就是findroot,answer两个操作;
根据分治的处理方法:分成若干个子问题
因此,在每次dfs都要查找root;据说这样就是优化。。。。
http://poj.org/problem?id=1741
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
#include<algorithm>
#include<map>
#define MAXX 1000001
#define INF 10000001
using namespace std;
int son[MAXX],deep[MAXX],d[MAXX],head[MAXX],tot,f[MAXX],n,k,sum,root,ans;
bool vis[MAXX];
struct data{
int nxt,to,w;
}edge[MAXX*2];
void add(int from,int too,int ww){edge[++tot].nxt=head[from],head[from]=tot,edge[tot].w=ww,edge[tot].to=too;}
void findroot(int num,int fa){
son[num]=1;f[num]=0;
for(int i=head[num];i;i=edge[i].nxt)if(fa!=edge[i].to&&!vis[edge[i].to]){
int too=edge[i].to;
findroot(too,num);
son[num]+=son[too];
f[num]=max(f[num],son[too]);
}
f[num]=max(f[num],sum-f[num]);
if(f[num]<f[root])root=num;
}
void finddeep(int num,int fa){
deep[++deep[0]]=d[num];
for(int i=head[num];i;i=edge[i].nxt)if(!vis[edge[i].to]&&fa!=edge[i].to){
int too=edge[i].to;
d[too]=d[num]+edge[i].w;
finddeep(too,num);
}
}
int an(int num,int dis){
deep[0]=0;d[num]=dis;
finddeep(num,0);
int tot1=0,l=1,r=deep[0];
sort(deep+1,deep+deep[0]+1);
while(l<r){
if(deep[r]+deep[l]<=k)tot1+=r-l,l++;
else r--;
}
return tot1;
}
void answer(int num){
ans+=an(num,0);
vis[num]=true;
for(int i=head[num];i;i=edge[i].nxt)if(!vis[edge[i].to]){
int too=edge[i].to;
ans-=an(too,edge[i].w);
sum=son[too];
root=0;
findroot(too,0);
answer(root);
}
}
int main(){
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
while(scanf("%d%d",&n,&k)&&n!=0&&k!=0){
ans=0,tot=0,sum=n;
for(int i=1;i<=n;++i)head[i]=0,vis[i]=false;
for(int i=1;i<n;++i){
int a,b,c;
scanf("%d%d%d",&a,&b,&c),add(a,b,c),add(b,a,c);
}
root=0;f[root]=INF;
findroot(1,0);
answer(root);
printf("%d\n",ans);
}
return 0;
}