月之暗面(入门级树形dp)

传送门

本题中,由于普通颜色和特殊颜色的种类下限为 1 1 1 ,因此对于树上的任意一个结点,都可以选择采用普通颜色或特殊颜色。通过状态 f [ i ] [ j ] f[i][j] f[i][j] 表示对于结点 i i i 采用 j j j 涂色的方案数,其中 j = 0 j=0 j=0 表示采用普通颜色, j = 1 j=1 j=1 表示采用特殊颜色。

由于相邻结点不能够使用同一种特殊颜色,因此若某一结点选择使用特殊颜色,则其儿子能够选择的颜色共有 x + y − 1 x+y-1 x+y1 种,即可以使用除其父亲选择的某种特殊颜色以外的其他颜色。而若某一结点选择使用普通颜色,则其儿子可无限制的选择 x + y x+y x+y 种颜色。

由此可得到转移方程:

f [ u ] [ 0 ] = f [ u ] [ 0 ] ∗ ( f [ v ] [ 0 ] ∗ x + f [ v ] [ 1 ] ∗ y ) f[u][0]=f[u][0]*(f[v][0]*x+f[v][1]*y) f[u][0]=f[u][0](f[v][0]x+f[v][1]y)

f [ u ] [ 1 ] = f [ u ] [ 1 ] ∗ ( f [ v ] [ 0 ] ∗ x + f [ v ] [ 1 ] ∗ ( y − 1 ) ) f[u][1]=f[u][1]*(f[v][0]*x+f[v][1]*(y-1)) f[u][1]=f[u][1](f[v][0]x+f[v][1](y1))

最后处理答案时,注意还要将根节点乘上可选择的颜色数。

#include <bits/stdc++.h>
#define int long long 
using namespace std;
const int N=1e6+10,mod=998244353;
int f[N][2];
vector<int> h[N];
/*
f[i][j]:表示当前结点为i 且采用的是j的涂色方案(0为普通 1为特殊)
父结点为0时 其儿子可以任意选色 为1时 其儿子只有一种特殊颜色不能选择
*/

int x,y;

void dfs(int u,int fa){
    f[u][0]=f[u][1]=1;
    for(auto v:h[u]){
        if(v==fa){
            continue;
        }
        dfs(v,u);
        f[u][0]=(f[u][0]*(f[v][0]*x%mod+f[v][1]*y%mod)%mod)%mod;
        f[u][1]=(f[u][1]*(f[v][0]*x%mod+f[v][1]*(y-1)%mod)%mod)%mod;
    }
}

signed main(){
    int n,u,v;
    cin>>n>>x>>y;
    for(int i=1;i<n;i++){
        cin>>u>>v;
        h[u].push_back(v);
        h[v].push_back(u);
    }
    
    dfs(1,0);
    int ans=f[1][0]*x%mod+f[1][1]*y%mod;
    cout<<ans%mod<<endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值