zoukankan      html  css  js  c++  java
  • CSU_1414 Query On a Tree BFS序+DFS时间戳进行预处理

    2014 csu校赛 I 题,比赛的时候拿着他看了几个小时愣是没弄出好的方法,我们也想过统计出每个root的节点总数,然后减去离它d层的子节点的数目,即为答案。但是因为树的存储是无序的,所以每次为了找到子节点还是需要搜索,这肯定是承受不了的。

    事实上,这个思路大体是对的,只是需要进行预处理,使得在找离它为d层的子节点能尽量节约时间,此外,如果找到了子节点挨个去减,也是很费时的,因为这些子节点必定处在同一层,他们的bfs序是连续的,故比较容易想到用前缀和来快速求得某一层的所有儿子的数目。

    我们看这样的树

    因此我们如果能把每个root的dfs时间戳的最小值和最大值给记录一下,再求出bfs序,则,对于某一层的所有节点,只要是时间戳在该root的最小值和最大值范围内,则必定是我们要求得孩子节点。

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #include <vector>
      6 #define N 100010
      7 using namespace std;
      8 vector <int> deep_num[N];
      9 int u[N],v[N],nt[N],ft[N],cnt,dfs_clock;
     10 int last[N][2],max_deep[N],tot[N],deep[N],sum[N];
     11 void add(int a,int b){
     12     u[cnt]=a;
     13     v[cnt]=b;
     14     nt[cnt]=ft[a];
     15     ft[a]=cnt++;
     16 }
     17 void init(int num)
     18 {
     19     cnt=0;
     20     dfs_clock=0;
     21     sum[0]=0;
     22 
     23     for (int i=0;i<=num;i++){
     24         ft[i]=-1;
     25         nt[i]=0;
     26         u[i]=v[i]=0;
     27         deep_num[i].clear();
     28         deep_num[i].push_back(0); //先给每个层预先加一个0,方便之后处理
     29     }
     30 }
     31 void dfs(int u,int d)
     32 {
     33     last[u][0]=++dfs_clock;
     34     deep_num[d].push_back(u);//这里直接把节点存入相应的层,省去了BFS,直接达到了计算BFS序的作用
     35     tot[u]=1;
     36     deep[u]=d;
     37     max_deep[u]=d;
     38     for (int w=ft[u];w>=0;w=nt[w]){
     39         int x=v[w];
     40         dfs(x,d+1);
     41         tot[u]+=tot[x];//计算root节点下的节点总数
     42         max_deep[u]=max(max_deep[u],max_deep[x]);//记录该root最大层有多深
     43     }
     44     last[u][1]=dfs_clock;
     45     if (deep_num[deep[u]].size()>1)
     46         sum[u]=sum[deep_num[deep[u]][deep_num[deep[u]].size()-2]]+tot[u];//因为没有进行BFS,所以计算前缀和要稍微麻烦一点,根据存贮好的每一层的节点来计算
     47     else
     48         sum[u]=sum[deep_num[deep[u]-1][deep_num[deep[u]-1].size()-1]]+tot[u];
     49 }
     50 int query(int x,int d)
     51 {
     52     if (max_deep[x]<=deep[x]+d-1)//如果该root没有那一层的孩子,则可以直接返回,因为肯定不需要减孩子了
     53         return tot[x];
     54     int val=last[x][0];
     55     int ret=tot[x];
     56     int nd=deep[x]+d;
     57     int L=0,R=deep_num[nd].size()-1,mid;
     58     int a,b;
     59     while (L<R)//
     60     {
     61 
     62         mid=(L+R)/2;
     63         //cout<<L<<" "<<R<<" "<<mid<<endl;
     64         int nx=deep_num[nd][mid];
     65         if (last[nx][0]>=val) R=mid;
     66         else L=mid+1;
     67         //cout<<nx<<" !!! "<<endl;
     68     }
     69     //cout<<"pass"<<endl;
     70     a=deep_num[nd][L-1];算出左边界,因为要算前缀和,所以L-1,这样前面的push 0在这里也起到作用了
     71     val=last[x][1];
     72     L=0,R=deep_num[nd].size()-1;
     73     while (L<R)
     74     {
     75         mid=R-(R-L)/2;
     76         int nx=deep_num[nd][mid];
     77         if (last[nx][1]<=val) L=mid;
     78         else R=mid-1;
     79        // cout<<nx<<" ~~ "<<endl;
     80     }
     81     b=deep_num[nd][R];
     82     //cout<<a<<" ab "<<b<<endl;
     83     //cout<<sum[a]<<" sum "<<sum[b]<<endl;
     84     ret-=sum[b]-sum[a]; //减去前缀和,其实还有个细节就是因为刚刚已经判断了,所以一定有孩子在这一层,所以这样减一定是合理的,不会出现没孩子也减掉的情况
     85     return ret;
     86 
     87 }
     88 int main()
     89 {
     90     int t,n,m,x,d;
     91     scanf("%d",&t);
     92     while (t--){
     93         scanf("%d",&n);
     94         init(n);
     95         for (int i=2;i<=n;i++){
     96             int tmp;
     97             scanf("%d",&tmp);
     98             add(tmp,i);
     99         }
    100         dfs(1,1);
    101         scanf("%d",&m);
    102         while (m--){
    103             scanf("%d%d",&x,&d);
    104             int ans=query(x,d);
    105             printf("%d
    ",ans);
    106         }
    107     }
    108     return 0;
    109 }
  • 相关阅读:
    吴裕雄 python 机器学习——高斯贝叶斯分类器GaussianNB
    吴裕雄 python 机器学习——分类决策树模型
    吴裕雄 python 机器学习——回归决策树模型
    吴裕雄 python 机器学习——线性判断分析LinearDiscriminantAnalysis
    吴裕雄 python 机器学习——逻辑回归
    吴裕雄 python 机器学习——ElasticNet回归
    吴裕雄 python 机器学习——Lasso回归
    吴裕雄 python 机器学习——岭回归
    吴裕雄 python 机器学习——线性回归模型
    【2017 Multi-University Training Contest
  • 原文地址:https://www.cnblogs.com/kkrisen/p/3688928.html
Copyright © 2011-2022 走看看