zoukankan      html  css  js  c++  java
  • CodeForces161D: Distance in Tree(树分治)

    tree is a connected graph that doesn't contain any cycles.

    The distance between two vertices of a tree is the length (in edges) of the shortest path between these vertices.

    You are given a tree with n vertices and a positive number k. Find the number of distinct pairs of the vertices which have a distance of exactly k between them. Note that pairs (vu) and (uv) are considered to be the same pair.

    Input

    The first line contains two integers n and k (1 ≤ n ≤ 50000, 1 ≤ k ≤ 500) — the number of vertices and the required distance between the vertices.

    Next n - 1 lines describe the edges as "ai bi" (without the quotes) (1 ≤ ai, bi ≤ nai ≠ bi), where ai and bi are the vertices connected by the i-th edge. All given edges are different.

    Output

    Print a single integer — the number of distinct pairs of the tree's vertices which have a distance of exactly k between them.

    Please do not use the %lld specifier to read or write 64-bit integers in С++. It is preferred to use the cin, cout streams or the %I64d specifier.

    Examples

    Input
    5 2
    1 2
    2 3
    3 4
    2 5
    Output
    4
    Input
    5 3
    1 2
    2 3
    3 4
    4 5
    Output
    2

    题意:给定一棵树,问树上有多少个点对距离是K(K<=500)。

    思路:明显的基础分治题,分别累计经过根节点的距离为K的点对。说他基础是以为既不需要排序,也不需要去重。复杂度O(NlogN*K)

    (感悟:分治=若干个小分治+线性解决当前层 =NlogN。

                  分治=若干个小分治+logN解决当前层 =NlogN*logN。

                  分治=若干个小分治+K*线性解决当前层 =N*K*logN。

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=100050;
    int Laxt[maxn],Next[maxn],To[maxn];
    int sz[maxn],son[maxn],root,cnt,N,K,ans,sn; //sn,小树的大小。 
    int num[550],tnum[550],vis[maxn];
    void read(int &x){
        x=0;     char c=getchar();
        while(c>'9'||c<'0') c=getchar();
        while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-'0',c=getchar();
    }
    void add(int u,int v)
    {
        Next[++cnt]=Laxt[u];
        Laxt[u]=cnt; To[cnt]=v;
    } 
    void getroot(int u,int fa)
    {
        sz[u]=1; son[u]=0;
        for(int i=Laxt[u];i;i=Next[i]){
            int v=To[i];
            if(v==fa||vis[v]) continue;
            getroot(v,u); sz[u]+=sz[v];
            son[u]=max(son[u],sz[v]);
        }
        son[u]=max(sz[u],sn-son[u]);
        if(root==0||son[root]>son[u]) root=u;
    }
    void getdep(int u,int fa,int dis)
    {
        if(K>=dis) ans+=num[K-dis],tnum[dis]++;
        if(K==dis)  return ;
        for(int i=Laxt[u];i;i=Next[i])
          if(To[i]!=fa&&!vis[To[i]]) 
            getdep(To[i],u,dis+1);
    }
    void dfs(int u)
    {
        vis[u]=1;
        for(int i=1;i<=K;i++) num[i]=0; num[0]=1; 
        for(int i=Laxt[u];i;i=Next[i]){         //暴力部分 
            if(vis[To[i]]) continue;
            for(int j=0;j<=K;j++) tnum[j]=0;
            getdep(To[i],0,1);
            for(int j=0;j<=K;j++) num[j]+=tnum[j];
        }
        
        for(int i=Laxt[u];i;i=Next[i]){      //以大化小,分治部分 
            if(vis[To[i]]) continue;
            sn=sz[To[i]]; root=0; 
            getroot(To[i],u); dfs(root);
        } 
    }
    int main()
    {
        int u,v; scanf("%d%d",&N,&K);
        for(int i=1;i<N;i++){
            read(u) ; read(v) ;
            add(u,v); add(v,u);
        }
        root=0; sn=N; getroot(1,0); dfs(root); 
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    docker 安装 redis
    docker 安装 fastdfs
    docker 安装 mysql5.7
    docker 安装 nacos
    docker 安装 gitlab-ce
    gitlab记录
    git记录
    ubuntu命令
    java html table 转 excel,给予jdom 和 poi
    自律挑战
  • 原文地址:https://www.cnblogs.com/hua-dong/p/9083072.html
Copyright © 2011-2022 走看看