Crystal

Crystal

颜色显然具有对称性,下文都只考虑其中一种情况,答案记得乘以二。

设每一个点到异色点的最短距离为 \(f(u)\),那么一组 \(f\) 与一种颜色状态一一对应。

尝试证明,必要性显然,考虑充分性。当且仅当相邻的两个点值同时为 \(1\) 时,两个点颜色不同,据此我们可以划分整棵树,从而确定颜色状态。

一组合法的 \(f(u)\) 需要满足以下条件:

  1. 对于任意的\(u\),使得\(f(u) \geq 1\)

  2. 对于任意相邻的\(u\)\(v\),使得\(| f(u) - f(v) | \leq 1\)

  3. 对于任意的\(u\),存在一个相邻的\(v\),使得\(| f(u) - f(v) | = 1\)

  4. \(f(u) = f(v) = 1\) 其中 \(u\)\(v\) 相邻时,\(u\)\(v\) 异色,不需要满足条件三。

接下来考虑 树形DP,设 \(g(u,x,0/1)\) 表示以 \(u\) 为根的子树中,使得\(f(u) = x\)\(u\) 的儿子是或否令其满足条件三或条件四的答案。

明确一下要求的答案:

\(\sum s (\sum x) ^ k\),其中 \(s\) 指状态。

首先,转移过程中我们肯定需要以某种方式将各儿子的答案合并。

合并的结果为 \(\sum s (\sum x + \sum y) ^ k\)

而我们只知道 \(\sum s (\sum x) ^ k\)\(\sum s (\sum y) ^ k\)

不妨将合并的结果通过二项式定理展开,这样,我们只记录 \(k \in [0,3]\) 下的所有答案即可。

接下来,细看转移方程。

乘法即二项式定理合并。

总的思路就是枚举儿子人后不断合并。

实在不知道怎么讲了,看代码吧。

for(int u=n;u>=1;u--){//枚举父亲,倒序枚举省去DFS
    for(int x=1;x<=n;x++){
        f[u][x][0].Init(x);//初始化
        f[u][x][1].Init(0);
        for(int v:E[u]){//枚举儿子
            tmp[0].Init(0);//临时变量
            tmp[1].Init(0);
            for(int y=max(1ll,x-1);y<=min(x+1,n);y++){//满足条件二
                if(y==x+1){//父亲可以令儿子满足条件三,儿子可以取0或1
                    tmp[0]+=(f[v][y][0]+f[v][y][1])*f[u][x][0];
                    tmp[1]+=(f[v][y][0]+f[v][y][1])*f[u][x][1];
                    //只需要有一个儿子使父亲满足即可,所以仍然选择合并。
                    //因为这一项初始值为0所以排除了全部儿子都不能使父亲满足的情况
                }
                else if(y==x-1){//儿子可以令父亲满足条件三,父亲可以取0或1
                    tmp[1]+=f[v][y][1]*(f[u][x][1]+f[u][x][0]);
                }
                else{//互不能使满足条件三,儿子必须靠孙子满足条件三
                    tmp[0]+=f[v][y][1]*f[u][x][0];
                    tmp[1]+=f[v][y][1]*f[u][x][1];
                    if(x==1&&y==1){//u,v颜色不同,可以任意取,条件四满足
                        tmp[1]+=(f[v][y][0]+f[v][y][1])*(f[u][x][1]+f[u][x][0]);
                    }
                }
            }
            f[u][x][0]=tmp[0];//赋值
            f[u][x][1]=tmp[1];
        }
    }
}

表达能力不好,靠个人理解吧。

代码链接

posted @ 2024-05-07 21:55  DeepSeaSpray  阅读(14)  评论(0编辑  收藏  举报