zoukankan      html  css  js  c++  java
  • Codeforces 161.D. Distance in Tree-树分治(点分治,不容斥版)-树上距离为K的点对数量-蜜汁TLE (VK Cup 2012 Round 1)

    time limit per test
    3 seconds
    memory limit per test
    512 megabytes
    input
    standard input
    output
    standard output

    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
    Copy
    5 2
    1 2
    2 3
    3 4
    2 5
    output
    Copy
    4
    input
    Copy
    5 3
    1 2
    2 3
    3 4
    4 5
    output
    Copy
    2
    Note

    In the first sample the pairs of vertexes at distance 2 from each other are (1, 3), (1, 5), (3, 5) and (2, 4).

    这道题就是求树上距离为K的点对数量。以前写过<=K的点对数量,直接<=K的数量 - <K的数量,讲道理应该也是可以的,但是一直TLE11和TLE17样例。。。

    最后换了一种写法,直接求,没有中间-子树的过程,最后过了,有点迷。。。

    不容斥版的快,就这样。

    代码:

      1 //树分治-点分治
      2 #include<bits/stdc++.h>
      3 using namespace std;
      4 typedef long long ll;
      5 //#pragma GCC optimize(2)
      6 //#define FI(n) FastIO::read(n)
      7 const int inf=1e9+7;
      8 const int maxn=1e5+10;
      9 const int maxm=500+10;
     10 
     11 int head[maxn<<1],tot;
     12 int root,allnode,n,m,k;
     13 bool vis[maxn];
     14 int deep[maxn],dis[maxn],siz[maxn],maxv[maxn];//deep[0]子节点个数(路径长度),maxv为重心节点
     15 int num[maxm],cnt[maxm];
     16 ll ans=0;
     17 
     18 //namespace FastIO {//读入挂
     19 //    const int SIZE = 1 << 16;
     20 //    char buf[SIZE], obuf[SIZE], str[60];
     21 //    int bi = SIZE, bn = SIZE, opt;
     22 //    int read(char *s) {
     23 //        while (bn) {
     24 //            for (; bi < bn && buf[bi] <= ' '; bi++);
     25 //            if (bi < bn) break;
     26 //            bn = fread(buf, 1, SIZE, stdin);
     27 //            bi = 0;
     28 //        }
     29 //        int sn = 0;
     30 //        while (bn) {
     31 //            for (; bi < bn && buf[bi] > ' '; bi++) s[sn++] = buf[bi];
     32 //            if (bi < bn) break;
     33 //            bn = fread(buf, 1, SIZE, stdin);
     34 //            bi = 0;
     35 //        }
     36 //        s[sn] = 0;
     37 //        return sn;
     38 //    }
     39 //    bool read(int& x) {
     40 //        int n = read(str), bf;
     41 //
     42 //        if (!n) return 0;
     43 //        int i = 0; if (str[i] == '-') bf = -1, i++; else bf = 1;
     44 //        for (x = 0; i < n; i++) x = x * 10 + str[i] - '0';
     45 //        if (bf < 0) x = -x;
     46 //        return 1;
     47 //    }
     48 //};
     49 
     50 inline int read()
     51 {
     52     int x=0;char ch=getchar();
     53     while(ch<'0'||ch>'9')ch=getchar();
     54     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
     55     return x;
     56 }
     57 
     58 struct node{
     59     int to,next,val;
     60 }edge[maxn<<1];
     61 
     62 void add(int u,int v,int w)//前向星存图
     63 {
     64     edge[tot].to=v;
     65     edge[tot].next=head[u];
     66     edge[tot].val=w;
     67     head[u]=tot++;
     68 }
     69 
     70 void init()//初始化
     71 {
     72     memset(head,-1,sizeof head);
     73     memset(vis,0,sizeof vis);
     74     tot=0;
     75 }
     76 
     77 void get_root(int u,int father)//重心
     78 {
     79     siz[u]=1;maxv[u]=0;
     80     for(int i=head[u];~i;i=edge[i].next){
     81         int v=edge[i].to;
     82         if(v==father||vis[v]) continue;
     83         get_root(v,u);//递归得到子树大小
     84         siz[u]+=siz[v];
     85         maxv[u]=max(maxv[u],siz[v]);//更新u节点的maxv
     86     }
     87     maxv[u]=max(maxv[u],allnode-siz[u]);//保存节点size
     88     if(maxv[u]<maxv[root]) root=u;//更新当前子树的重心
     89 }
     90 
     91 void get_dis(int u,int father)//获取子树所有节点与根的距离
     92 {
     93     if(dis[u]>k) return ;
     94     ans+=num[k-dis[u]];
     95     cnt[dis[u]]++;//计数
     96     for(int i=head[u];~i;i=edge[i].next){
     97         int v=edge[i].to;
     98         if(v==father||vis[v]) continue;
     99         int w=edge[i].val;
    100         dis[v]=dis[u]+w;
    101         get_dis(v,u);
    102     }
    103 }
    104 
    105 void cal(int u,int now)
    106 {
    107     for(int i=1;i<=k;i++){//初始化,清空
    108         num[i]=0;
    109     }
    110     num[0]=1;
    111     for(int i=head[u];~i;i=edge[i].next){
    112         int v=edge[i].to;
    113         if(vis[v]) continue;
    114         for(int j=0;j<=k;j++){//初始化
    115             cnt[j]=0;
    116         }
    117         dis[v]=now;
    118         get_dis(v,u);//跑路径
    119         for(int j=0;j<=k;j++){
    120             num[j]+=cnt[j];//计数
    121         }
    122     }
    123 }
    124 
    125 void solve(int u)//分治处理
    126 {
    127     cal(u,1);
    128     vis[u]=1;
    129     for(int i=head[u];~i;i=edge[i].next){
    130         int v=edge[i].to;
    131         int w=edge[i].val;
    132         if(vis[v]) continue;
    133         allnode=siz[v];
    134         root=0;
    135         get_root(v,u);
    136         solve(root);
    137     }
    138 }
    139 
    140 int main()
    141 {
    142 //    FI(n);FI(k);
    143     n=read();k=read();
    144     init();
    145     for(int i=1;i<n;i++){
    146         int u,v,w;w=1;
    147 //        FI(u);FI(v);
    148         u=read();v=read();
    149         add(u,v,w);
    150         add(v,u,w);
    151     }
    152     root=0;allnode=n;maxv[0]=inf;
    153     get_root(1,0);
    154     solve(root);
    155     printf("%lld
    ",ans);
    156     return 0;
    157 }
  • 相关阅读:
    Explainable ML
    Fizz Buzz in tensorflow
    Tips for traing DNN (Adam,正则化,Dropout)
    深度学习 高数知识
    perror strerror使用方法
    posix信号量与互斥锁
    线程基本操作(一)
    system v共享内存与信号量综合
    shell统计当前文件夹下的文件个数、目录个数
    栈 c实现
  • 原文地址:https://www.cnblogs.com/ZERO-/p/11672233.html
Copyright © 2011-2022 走看看