HDU5593 ZYB's Tree 树形DP +分治

感觉其实就是树分治,一次BC的题,感觉这次题目质量比较高,仅代表蒟蒻的看法

一次DFS获取每个点到子树的距离不大于K的点的个数,

然后一遍BFS获取从每个点父亲不大于K的的个数,层层扩展,还是想说 其实就是树分治。。。。。并没有什么DP

/*
Problem : 5593 ( ZYB's Tree )     Judge Status : Accepted
RunId : 15764784    Language : G++    Author : qianbi08
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<iostream>
#include<cstdlib>
#include<queue>
using namespace std;
const int maxn=500005;
int head[maxn],fa[maxn],p;
int dp[maxn][11],n,k,a,b;
struct Edge
{
    int v,next;
}edge[maxn*2];
void addedge(int u,int v)
{
    edge[p].v=v;
    edge[p].next=head[u];
    head[u]=p++;
}
void dfs(int u)
{
    dp[u][0]=1;
    for(int i=head[u];~i;i=edge[i].next)
    {
        int v=edge[i].v;
        if(v==fa[u])continue;
        dfs(v);
        for(int j=1;j<=k;j++)
         dp[u][j]+=dp[v][j-1];
    }
}
queue<int>q;
void bfs()
{
   while(!q.empty())q.pop();
   for(int i=head[1];~i;i=edge[i].next)
       q.push(edge[i].v);
   while(!q.empty())
   {
       int u=q.front();
       q.pop();
       for(int i=k;i>1;--i)
        dp[u][i]+=dp[fa[u]][i-1]-dp[u][i-2];
       ++dp[u][1];
       for(int i=head[u];~i;i=edge[i].next)
          if(edge[i].v!=fa[u])q.push(edge[i].v);
   }
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d%d%d",&n,&k,&a,&b);
        memset(head,-1,sizeof(head));
        memset(dp,0,sizeof(dp));
        p=0;
        fa[1]=0;
        long long aa=a;
        for(int i=2;i<=n;i++)
        {
            aa+=a;
            int u=(aa+b)%(i-1)+1;
            int v=i;
            fa[v]=u;
            addedge(u,v);
            addedge(v,u);
        }
        dfs(1);
        bfs();
        int ans;
        for(int i=1;i<=n;i++)
        {
           int sum=0;
           for(int j=0;j<=k;j++)
            sum+=dp[i][j];
           if(i==1)ans=sum;
           else ans^=sum;
        }
        printf("%d\n",ans);
    }
    return 0;
}
View Code

 

posted @ 2015-12-06 12:07  shuguangzw  阅读(184)  评论(0编辑  收藏  举报