本题中,由于普通颜色和特殊颜色的种类下限为 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+y−1 种,即可以使用除其父亲选择的某种特殊颜色以外的其他颜色。而若某一结点选择使用普通颜色,则其儿子可无限制的选择 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]∗(y−1))
最后处理答案时,注意还要将根节点乘上可选择的颜色数。
#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;
}