目录
题目描述
I'll see you on the dark side of the moon.
我们将在月之暗面相会。
给出一棵 n个点的树,有 x 种普通颜色,y 种特殊颜色
现在要给树上的每个节点染色,普通颜色染色没有限制,但两个相邻的节点不能染相同颜色的特殊颜色
求染色方案数,答案对 998244353 取模。
输入描述:
第一行三个整数 n,x,y ( 1≤n≤106,1≤x,y≤109 ) ,分别表示树的节点数,普通颜色的种数,特殊颜色的种数
接下来n−1 行描述这棵树,每行两个整数 u,v( 1≤u,v,≤n ) 表示从 u 到 v 有一条树边
保证输入的树合法。
输出描述:
一行一个整数,表示答案。
示例1
输入
2 1 2 1 2
输出
7
示例2
输入
5 3 3 1 2 1 3 3 4 3 5
输出
5664
示例3
输入
11 45 14 6 5 6 7 7 9 7 8 9 2 8 10 2 1 8 3 10 4 4 11
输出
188688550
思路:
1,用链式前向星建树,用转移方程做题
2,dp[i][j]第i节点,j表示的是普通颜色还是特殊颜色,
3,dp[i][0]=dp[i][0]*(dp[i-1][0]*x%mod+dp[i-1][1]*y%mod)%mod;该位为普通颜色
dp[i][1]=dp[i][1]*(dp[i-1][0]*x%mod+dp[i-1][1]*(y-1)%mod)%mod;该位为特殊颜色
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxj = 1e6+100 , mod = 998244353;
int v[maxj],dp[maxj][2],tot,nex[maxj],head[maxj],vis[maxj];
int n,x,y;
void add ( int u, int v1 ){
++tot;
v[tot]=v1;
nex[tot] = head[u];
head[u]=tot;//链式前向星
}
void dfs(int u,int fa){
dp[u][0] = dp[u][1] = 1;
for(int i = head[u] ; i ; i = nex[i] ) {
int v1 = v[i] ;
if(v1 == fa) continue ;
dfs(v1,u);
dp[u][0]=dp[u][0]*(dp[v1][0]*x%mod+dp[v1][1]*y%mod)%mod;
dp[u][1]=dp[u][1]*(dp[v1][0]*x%mod+dp[v1][1]*(y-1)%mod)%mod;
}
}
int32_t main(){
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
cin>>n>>x>>y;
int be=1;
int flag=1;
for(int i=1;i<=n-1;++i){
int u,v;
cin>>u>>v;
// if(flag){
// be=u;
// flag=0;
// }
add(u,v);//有向图,从没到达过的地方开始
// add(v,u);//无向图,从没开始的地方开始,开始不同
vis[v]++;
}
for(int i=1;i<=n-1;++i){
if(vis[i]==0){be=i;break;}
}
dfs(be,-1);
cout<<(dp[be][0]*x%mod+dp[be][1]*y%mod)%mod<<'\n';
return 0;
}