poj 1744 tree 树分治

Tree

Time Limit: 1000MS   Memory Limit: 30000K
     

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

Source

[email protected]

树分治模板题;

分治算法在树的路径问题中的应用

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<iostream>
#include<cstdio>
#include<cmath>
#include<string>
#include<queue>
#include<algorithm>
#include<stack>
#include<cstring>
#include<vector>
#include<list>
#include<set>
#include<map>
using namespace std;
#define LL long long
#define pi (4*atan(1.0))
#define eps 1e-8
#define bug(x)  cout<<"bug"<<x<<endl;
const int N=1e4+10,M=2e6+10,inf=1e9+10;
const LL INF=1e18+10,mod=1e9+7;

struct is
{
    int v,w,nex;
}edge[N<<1];
int head[N],edg;
void add(int u,int v,int w)
{
    edge[++edg]=(is){v,w,head[u]};head[u]=edg;
}

int son[N],msi[N],d[N];
int vis[N],deep[N];
int n,K,ans,root,sum;
void groot(int u,int fa)
{
    son[u]=1,msi[u]=0;
    for(int i=head[u];i!=-1;i=edge[i].nex)
    {
        int v=edge[i].v;
        if(v==fa||vis[v])continue;
        groot(v,u);
        son[u]+=son[v];
        msi[u]=max(msi[u],son[v]);
    }
    msi[u]=max(msi[u],sum-son[u]);
    if(msi[u]<msi[root])root=u;
}
void gdeep(int x,int fa)
{
    deep[++deep[0]]=d[x];
    for(int i=head[x];i!=-1;i=edge[i].nex)
    {
        int v=edge[i].v;
        int w=edge[i].w;
        if(v==fa||vis[v])continue;
        d[v]=d[x]+w;
        gdeep(v,x);
    }
}

int rootans(int x,int base)
{
    d[x]=base;deep[0]=0;
    gdeep(x,0);
    sort(deep+1,deep+1+deep[0]);
    int ans=0,l=1,r=deep[0];
    while(l<r)
    {
        if(deep[l]+deep[r]<=K)
        {
            ans+=r-l;
            l++;
        }
        else r--;
    }
    return ans;
}
void dfs(int u)
{
    ans+=rootans(u,0);
    vis[u]=1;
    for(int i=head[u];i!=-1;i=edge[i].nex)
    {
        int v=edge[i].v;
        int w=edge[i].w;
        if(vis[v])continue;
        ans-=rootans(v,w);
        root=0;sum=son[v];
        groot(v,u);
        dfs(root);
    }
}
void init(int n)
{
    memset(head,-1,sizeof(head));
    memset(msi,0,sizeof(msi));
    memset(son,0,sizeof(son));
    memset(d,0,sizeof(d));
    memset(vis,0,sizeof(vis));
    memset(deep,0,sizeof(deep));
    sum=n;root=0;edg=0;
    msi[0]=inf;
    ans=0;
}
int main()
{
    while(~scanf("%d%d",&n,&K))
    {
        if(n==0&&K==0)break;
        init(n);
        for(int i=1;i<n;i++)
        {
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            add(u,v,w);
            add(v,u,w);
        }
        groot(1,0);
        dfs(root);
        printf("%d\n",ans);
    }
    return 0;
}
时间: 07-28