[bzoj3696]化合物_树形dp

Posted shurak

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[bzoj3696]化合物_树形dp相关的知识,希望对你有一定的参考价值。

化合物 bzoj-3696

题目大意:给你一棵树,定义两个点i , j之间的A值是(dis[i]-dis[lca(i,j)])xor(dis[j]-dis[lca(i,j)])。对所有的k$in$[1,n],A值等于k的点对数量。

注释:$1le nle 10^5$,$1le maxdis le 500$。

想法:说什么异或意义下的母函数,完全不会(具体数学没看完的垃圾蒟蒻)。其实就是个暴力...

我们设dp[pos][i]表示以pos为根,长度为i的链的个数,然后直接转移。每次$H^2$扫,复杂度$O(Ncdot H^2)$,然后... ...就过了。

最后,附上丑陋的代码... ...

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 100010
#define M 101000 
using namespace std;
int n,num[M][510],ans[1024];
int head[M],to[M],nxt[M],tot;
void add(int x,int y)
{
    to[++tot]=y;
	nxt[tot]=head[x];
	head[x]=tot;
}
int dfs(int x)
{
    int mx=0; num[x][0]=1;
    for(int i=head[x];i;i=nxt[i])
    {
        int tmp=dfs(to[i])+1; mx=max(mx,tmp);
        for(int j=1;j<=tmp;++j)
            for(int k=0;k<=mx;++k)
                ans[k^j]+=num[x][k]*num[to[i]][j-1];
        for(int j=1;j<=tmp;++j) num[x][j]+=num[to[i]][j-1];
    }
    return mx;
}
int main()
{
    scanf("%d",&n); int x;
    for(int i=2;i<=n;++i)
    {
        scanf("%d",&x);
        add(x,i);
    }
    dfs(1); int now;
    for(int i=512;i>=0;i--) if(ans[i]){ now=i; break; }
    for(int i=0;i<=now;++i) printf("%d
",ans[i]);
    return 0;
}

小结:这种题,不指望自己考试能切了

以上是关于[bzoj3696]化合物_树形dp的主要内容,如果未能解决你的问题,请参考以下文章

bzoj3696化合物 树形dp

BZOJ 3696 化合物

bzoj3696

BZOJ_1060_时态同步_树形DP

BZOJ_1864_[Zjoi2006]三色二叉树_树形DP

[bzoj2657][Zjoi2012]旅游 journey_ 对偶图_树形dp