點分治(模板)

Tree

 POJ - 1741 

 

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的節點的對數 

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=200005;
struct node
{
    int next,to,value;
} edge[maxn];
int head[maxn],cnt_edge,cnt,Size[maxn],max_son[maxn],root,n,m,dis[maxn],deep[maxn],ans,vis[maxn],sum;
void add(int u,int v,int w)
{
    edge[cnt_edge].to = v;
    edge[cnt_edge].value = w;
    edge[cnt_edge].next = head[u];
    head[u] = cnt_edge++;
}

void get_core(int x,int father)
{
    Size[x] = 1;
    max_son[x] = father;
    for(int i = head[x]; i !=-1; i = edge[i].next)
    {
        int to = edge[i].to;
        if(to ==father||vis[to])
            continue;
        get_core(to,x);
        Size[x] += Size[to];
        max_son[x] = max(max_son[x],Size[to]);
    }
    max_son[x] = max(max_son[x],sum-Size[x]);
    if(max_son[x]<max_son[root])
        root = x;
}

void get_deep(int x,int father)
{
    dis[++cnt] = deep[x];
    for(int i = head[x]; i!=-1; i = edge[i].next)
    {
        int to = edge[i].to;
        if(to ==father||vis[to])
            continue;
        deep[to] = deep[x]+edge[i].value;
        get_deep(to,x);
    }
}

int cal_node(int x,int add)
{
    cnt = 0;
    deep[x] = add;
    get_deep(x,0);
    sort(dis+1,dis+cnt+1);
    int l = 1;
    int r = cnt;
    int res = 0;
    while(l<r)
    {
        if(dis[l]+dis[r]<=m)
        {
            res +=r-l;
            l++;
        }
        else
            r --;
    }
    return res;
}

void solve(int x)
{
    ans +=cal_node(x,0);
    vis[x]  =1;
    for(int i = head[x]; i !=-1; i = edge[i].next)
    {
        int to = edge[i].to;
        if(vis[to])
            continue;
        ans -= cal_node(to,edge[i].value);
        sum = Size[to];
        root = 0;
        get_core(to,0);
        solve(root);
    }

}
int main()
{
    int i,a,b,c;
    while(scanf("%d %d",&n,&m)!=EOF)
    {
        if(n==0&&m==0)
            return 0;
            ans = 0;
        memset(head,-1,sizeof(head));
        memset(vis,0,sizeof(vis));
        cnt_edge = 0;
        for(i = 0; i < n-1; i++)
        {
            scanf("%d %d %d",&a,&b,&c);
            add(a,b,c);
            add(b,a,c);
        }
        root = 0;
        sum= max_son[0]= n;
        get_core(1,0);
        solve(root);
        printf("%d\n",ans);
    }
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章