【poj1741】Tree

来源:互联网 发布:淘宝店铺首页全屏轮播 编辑:程序博客网 时间:2024/06/06 01:49

Description

Give a tree with n vertices,each edge has a length(positive integer less than 1001).
Define dist(u,v)=The min distance between node u and v.
Give an integer k,for every pair (u,v) of vertices is called valid if and only if dist(u,v) not exceed k.
Write a program that will count how many pairs which are valid for a given tree.
Input

The input contains several test cases. The first line of each test case contains two integers n, k. (n<=10000) The following n-1 lines each contains three integers u,v,l, which means there is an edge between node u and v of length l.
The last test case is followed by two zeros.
Output

For each test case output the answer on a single line.
Sample Input

5 4
1 2 3
1 3 1
1 4 2
3 5 1
0 0
Sample Output

8

题目大意
求树上长度小于等于k的链有几条
题解
对于这题 可以对这个点延伸出的几棵子树各做一次dfs
记录子树中出现的距离值
对于一棵树的距离值数组
把它排序求一次ans1
再对每棵子树分别求一个自己对自己的ans2
ans1−∑ans2即为最后的ans

代码

#include<cstring>#include<iostream>#include<cmath>#include<cstdio>#include<algorithm>#define N 10005int n,m,k,tot,cnt,rt,ans;int size[N],ret[2*N],len[2*N],Next[2*N],Head[2*N];int a[N],dis[N];bool flag[N];using namespace std;inline int read(){    int x=0;char ch=getchar();    while (ch<'0'||ch>'9') ch=getchar();    while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}    return x;}inline void ins(int u,int v,int l){    tot++;    ret[tot]=v;    len[tot]=l;    Next[tot]=Head[u];    Head[u]=tot;}void find_pre(int u,int f)//预处理{    size[u]=1;    for (int i=Head[u];i;i=Next[i])    {        int v=ret[i];        if (v!=f&&!flag[v])         {            find_pre(v,u);            size[u]+=size[v];           }    }}int find_rt(int u,int f)//寻找重心{    for (int i=Head[u];i;i=Next[i])    {        int v=ret[i];        if (v!=f&&!flag[v])        {            if (size[v]>size[rt]/2) return find_rt(v,u);        }    }    return u;}void dfs(int u,int f)//计算点到根的距离{    for (int i=Head[u];i;i=Next[i])    {        int v=ret[i];        if (v!=f&&!flag[v])        {            dis[v]=dis[u]+len[i];            a[++cnt]=dis[v];            dfs(v,u);        }    }}int cal(int RT,int d)//计算答案{    dis[RT]=d;    cnt=1;    a[1]=d;    dfs(RT,0);    sort(a+1,a+cnt+1);    int t=0,l,r;    for(l=1,r=cnt;l<r;)    {        if(a[l]+a[r]<=k){t+=r-l;l++;}        else r--;    }    return t;}inline void solve(int RT){    ans+=cal(RT,0);    flag[RT]=1;    for (int i=Head[RT];i;i=Next[i])    {        int v=ret[i];        if (!flag[v])        {            ans-=cal(v,dis[v]);            find_pre(v,0);            rt=v;            solve(find_rt(rt,0));        }    }}int main(){    n=read();k=read();    while (n!=0&&k!=0)    {        tot=0;        for (int i=1;i<=n;i++)            flag[i]=Head[i]=0;        for (int i=1;i<n;i++)        {            int u=read(),v=read(),l=read();            ins(u,v,l);            ins(v,u,l);        }         find_pre(1,0);        rt=1;        ans=0;        solve(find_rt(1,0));        printf("%d\n",ans);        n=read();k=read();    }    return 0;}
0 0