poj 1741 Tree

题目大意:有一颗由n个点组成的树,问树上两点间距离小于等于k的点对有多少对
输入:多组数据输入。每组数据第1行n,k,接下来n-1行,u,v,l表示点u与点v之间有一条长为l的边
输出:点对个数

 

/*
    借此题说说对点分治的认识,点分治就是将一棵树分为几部分,使得最大的一部分的点数最小,也就是找树的重心
    对于经过重心的,
    1、统计出过重心的所有点的满足条件的数目=ans1
    2、对于每棵子树,统计一遍自己内部满足条件的数目=ans2
    ans=ans1-所有的ans2
    对于不经过重心的,继续递归
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define INF 0x7fffffff
#define maxn 10010
struct node{int to,v,pre;}e[maxn*2];
int n,num,k,root,sum,ans,head[maxn],f[maxn];
int vis[maxn],son[maxn],d[maxn],dep[maxn];
void Insert(int from,int to,int v){
    e[++num].to=to;
    e[num].v=v;
    e[num].pre=head[from];
    head[from]=num;
}
void getroot(int x,int fa){
    son[x]=1;f[x]=0;
    for(int i=head[x];i;i=e[i].pre){
        int to=e[i].to;
        if(to==fa||vis[to])continue;
        getroot(to,x);
        son[x]+=son[to];
        f[x]=max(f[x],son[to]);
    }
    f[x]=max(f[x],sum-son[x]);
    if(f[x]<f[root])root=x;
}
void getdeep(int x,int fa){
    dep[++dep[0]]=d[x];
    for(int i=head[x];i;i=e[i].pre){
        int to=e[i].to;
        if(to==fa||vis[to])continue;
        d[to]=d[x]+e[i].v;
        getdeep(to,x);
    }
}
int cal(int x,int v){
    d[x]=v;dep[0]=0;
    getdeep(x,0);
    sort(dep+1,dep+dep[0]+1);
    int l=1,r=dep[0],sum=0;
    while(l<r){
        if(dep[l]+dep[r]<=k){sum+=r-l;l++;}
        else r--;
    }
    return sum;
}
void solve(int x){
    ans+=cal(x,0);
    vis[x]=1;
    for(int i=head[x];i;i=e[i].pre){
        int to=e[i].to;
        if(vis[to])continue;
        ans-=cal(to,e[i].v);
        sum=son[to];
        root=0;
        getroot(to,0);
        solve(root);
    }
}
int main(){
    //freopen("Cola.txt","r",stdin);
    while(1){
        ans=0,root=0,num=0;
        memset(vis,0,sizeof(vis));
        memset(head,0,sizeof(head));
        scanf("%d%d",&n,&k);
        if(n==0&&k==0)break;
        for(int i=1;i<=n-1;i++){
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            Insert(x,y,z);Insert(y,x,z);
        }
        f[0]=INF;sum=n;
        getroot(1,0);
        solve(root);
        printf("%d\n",ans);
    }
    return 0;
}

 

posted @ 2017-12-16 10:33  Echo宝贝儿  阅读(159)  评论(0编辑  收藏  举报