// Hydro submission #66dea719a262ee455ee5b60c@1725868038379
// 那就是希望。
// 即便需要取模,也是光明。
// 牛逼题。
// 应该是目前国内官方赛场上出现过的最难的 DS 优化 dp 题。
// 没有之一。
// 容斥、长链剖分、可回退化数据结构、离线求逆元四倍役满!(雾)
#include <algorithm>
#include <stdio.h>
#include <vector>
typedef long long llt;
typedef unsigned uint;typedef unsigned long long ullt;
typedef bool bol;typedef char chr;typedef void voi;
typedef double dbl;
template<typename T>bol _max(T&a,T b){return(a<b)?a=b,true:false;}
template<typename T>bol _min(T&a,T b){return(b<a)?a=b,true:false;}
template<typename T>T lowbit(T n){return n&-n;}
template<typename T>T gcd(T a,T b){return b?gcd(b,a%b):a;}
template<typename T>T lcm(T a,T b){return(a!=0||b!=0)?a/gcd(a,b)*b:(T)0;}
template<typename T>T exgcd(T a,T b,T&x,T&y){if(b!=0){T ans=exgcd(b,a%b,y,x);y-=a/b*x;return ans;}else return y=0,x=1,a;}
template<typename T>T power(T base,T index,T mod)
{
T ans=1%mod;
while(index)
{
if(index&1)ans=ans*base%mod;
base=base*base%mod,index>>=1;
}
return ans;
}
namespace ConstMod
{
template<const ullt p>
class mod_ullt
{
private:
ullt v;
inline ullt chg(ullt w){return(w<p)?w:w-p;}
inline mod_ullt _chg(ullt w){mod_ullt ans;ans.v=(w<p)?w:w-p;return ans;}
public:
mod_ullt():v(0){}
mod_ullt(ullt v):v(v%p){}
bol empty(){return!v;}
inline ullt val(){return v;}
friend bol operator<(mod_ullt a,mod_ullt b){return a.v<b.v;}
friend bol operator>(mod_ullt a,mod_ullt b){return a.v>b.v;}
friend bol operator<=(mod_ullt a,mod_ullt b){return a.v<=b.v;}
friend bol operator>=(mod_ullt a,mod_ullt b){return a.v>=b.v;}
friend bol operator==(mod_ullt a,mod_ullt b){return a.v==b.v;}
friend bol operator!=(mod_ullt a,mod_ullt b){return a.v!=b.v;}
inline friend mod_ullt operator+(mod_ullt a,mod_ullt b){return a._chg(a.v+b.v);}
inline friend mod_ullt operator-(mod_ullt a,mod_ullt b){return a._chg(a.v+a.chg(p-b.v));}
inline friend mod_ullt operator*(mod_ullt a,mod_ullt b){return a.v*b.v;}
friend mod_ullt operator/(mod_ullt a,mod_ullt b){return b._power(p-2)*a.v;}
friend mod_ullt operator^(mod_ullt a,ullt b){return a._power(b);}
inline mod_ullt operator-(){return _chg(p-v);}
mod_ullt sqrt()
{
if(power(v,(p-1)>>1,p)!=1)return 0;
mod_ullt b=1;do b++;while(b._power((p-1)>>1)==1);
ullt t=p-1,s=0,k=1;while(!(t&1))s++,t>>=1;
mod_ullt x=_power((t+1)>>1),e=_power(t);
while(k<s)
{
if(e._power(1llu<<(s-k-1))!=1)x*=b._power((1llu<<(k-1))*t);
e=_power(p-2)*x*x,k++;
}
return _min(x,-x),x;
}
mod_ullt inv(){return _power(p-2);}
mod_ullt _power(ullt index){mod_ullt ans(1),w(v);while(index){if(index&1)ans*=w;w*=w,index>>=1;}return ans;}
voi read(){v=0;chr c;do c=getchar();while(c>'9'||c<'0');do v=(c-'0'+v*10)%p,c=getchar();while(c>='0'&&c<='9');v%=p;}
voi print()
{
static chr C[20];uint tp=0;
ullt w=v;do C[tp++]=w%10+'0',w/=10;while(w);
while(tp--)putchar(C[tp]);
}
voi println(){print(),putchar('\n');}
mod_ullt operator++(int){mod_ullt ans=*this;return v=chg(v+1),ans;}
public:
inline ullt&operator()(){return v;}
inline mod_ullt&operator+=(mod_ullt b){return*this=_chg(v+b.v);}
inline mod_ullt&operator-=(mod_ullt b){return*this=_chg(v+chg(p-b.v));}
inline mod_ullt&operator*=(mod_ullt b){return*this=v*b.v;}
mod_ullt&operator^=(ullt b){return*this=_power(b);}
mod_ullt&operator/=(mod_ullt b){return*this=b._power(p-2)*v;}
mod_ullt&operator++(){return v=chg(v+1),*this;}
};
}
const ullt Mod=998244353;
typedef ConstMod::mod_ullt<Mod>modint;
typedef std::vector<modint>modvec;
template<typename T> // 可回退化 DS
struct Roll{
std::vector<T*>At;std::vector<T>W;uint tp;
Roll():At(),W(),tp(0){}
voi clear(){At.clear(),W.clear(),tp=0;}
voi chg(T&p,T v){
if(At.size()>tp)At.resize(tp),W.resize(tp);
At.push_back(&p),W.push_back(p),p=v,tp++;
}
voi step_on(){if(tp<At.size())std::swap(*At[tp],W[tp]),tp++;}
voi step_back(){if(tp)--tp,std::swap(*At[tp],W[tp]);}
voi go_time(uint t){
_min(t,(uint)At.size());
while(tp<t)step_on();
while(tp>t)step_back();
}
};
modint _Base[20000005],*End=_Base+20000000;
modint*NewMemory(uint n){return End-=n;}
struct vec1{
modint*P,mul,add,inv,C;uint from,siz;Roll<uint>Ru;Roll<modint>Rv;
vec1():P(NULL),mul(1),add(),inv(1),C(),from(0),siz(0),Ru(),Rv(){}
voi build(uint len){P=NewMemory(len);}
voi chg(uint&a,uint b){Ru.chg(a,b);}
voi chg(modint&a,modint b){Rv.chg(a,b);}
modint val(uint p){return from+p>=siz?C:P[siz-p-1]*mul+add;}
voi push(){chg(P[siz],-add*inv),chg(C,C+1),chg(add,add+1),chg(siz,siz+1);}
voi merge(vec1&p){
while(from>siz-p.siz)chg(from,from-1),chg(P[from],(C-add)*inv);
modint a=p.val(1e9);
if(a.empty()){
for(uint i=0;i<p.siz;i++)chg(P[siz-i-1],(val(i)*p.val(i)-add)*inv);
chg(C,0),chg(from,siz-p.siz);
}
else{
for(uint i=0;i<p.siz;i++)chg(P[siz-i-1],val(i)*p.val(i));
chg(mul,mul*a),chg(add,add*a),chg(C,C*a),chg(inv,inv/a);
for(uint i=0;i<p.siz;i++)chg(P[siz-i-1],(P[siz-i-1]-add)*inv);
}
}
};
std::vector<uint>Way[1000005],Son[1000005];
uint Dep[1000005],MaxDep[1000005],Heavy[1000005],Fath[1000005],x;
voi dfs0(uint p,uint f){
Heavy[p]=-1,MaxDep[p]=Dep[p],Fath[p]=f;
for(auto s:Way[p])if(s!=f)Dep[s]=Dep[p]+1,dfs0(s,p),Son[p].push_back(s);
std::sort(Son[p].begin(),Son[p].end(),[&](uint a,uint b){return MaxDep[a]>MaxDep[b];});
if(Son[p].size())MaxDep[p]=MaxDep[Heavy[p]=Son[p][0]];
}
vec1 H[1000005];uint At[1000005];
modint GetVal[3][1000005];
uint Time[2][1000005];
voi dfs1(uint p,uint r){
if(~Heavy[p])dfs1(Heavy[p],r),At[p]=At[Heavy[p]];else H[At[p]=p].build(Dep[p]-Dep[r]+2);
vec1&h=H[At[p]];h.push();
for(auto s:Son[p])if(s!=Heavy[p])
dfs1(s,s),Time[0][s]=h.Ru.tp,Time[1][s]=h.Rv.tp,H[At[s]].push(),h.merge(H[At[s]]);
GetVal[0][p]=h.val(x);if(x)GetVal[1][p]=h.val(x-1);
}
struct vec2{
modint*P;modint add,mul,inv;uint siz;
vec2():P(NULL),add(),mul(1),inv(1),siz(){}
voi build(uint len){P=NewMemory(siz=len);}
modint val(uint p){return P[siz-p-1]*mul+add;}
voi pop(){siz--;}
};
vec2 G[1000005];uint At2[1000005];
voi dfs2(uint p){
vec1&h=H[At[p]];vec2&g=G[At2[p]];
if(!~Fath[p])g.build(MaxDep[p]+1),g.add=1;
GetVal[2][p]=g.val(0),g.pop();
if(!~Heavy[p])return;
std::reverse(Son[p].begin(),Son[p].end());
for(auto s:Son[p])if(s!=Heavy[p]){
h.Ru.go_time(Time[0][s]),h.Rv.go_time(Time[1][s]);
vec2&gs=G[At2[s]=s];
gs.build(MaxDep[s]-Dep[s]+1),gs.add=1;
for(uint i=0;i<gs.siz&&i<x;i++)
gs.P[gs.siz-i-1]=g.val(i)*h.val(x-i-1);
vec1&hs=H[At[s]];
if(hs.siz>=std::min(g.siz,x)){
for(uint i=0;i<g.siz&&i<x;i++)g.P[g.siz-i-1]=(hs.val(x-i-1)*g.val(i)-g.add)*g.inv;
}else{
if(hs.val(1e9).empty()){
for(uint i=0;i<g.siz&&i<x;i++)g.P[g.siz-i-1]=(hs.val(x-i-1)*g.val(i)-g.add)*g.inv;
}
else{
for(uint i=std::min(x,g.siz)-hs.siz;i<std::min(x,g.siz);i++)
g.P[g.siz-i-1]=hs.val(x-i-1)*g.val(i);
g.mul*=hs.val(1e9),g.add*=hs.val(1e9),g.inv/=hs.val(1e9);
for(uint i=std::min(x,g.siz)-hs.siz;i<std::min(x,g.siz);i++)
g.P[g.siz-i-1]=(g.P[g.siz-i-1]-g.add)*g.inv;
}
}
dfs2(s);
}
if(g.siz>x)g.P[g.siz-x-1]=-g.add*g.inv;
G[At2[Heavy[p]]=At2[p]].add++,dfs2(Heavy[p]);
}
int main()
{
#ifdef MYEE
freopen("QAQ.in","r",stdin);
#endif
uint n,k;scanf("%u%u%u",&n,&x,&k);
for(uint i=1,u,v;i<n;i++)scanf("%u%u",&u,&v),Way[--u].push_back(--v),Way[v].push_back(u);
dfs0(0,-1),dfs1(0,0),dfs2(0);
// for(uint i=0;i<n;i++)GetVal[0][i].print(),putchar(" \n"[i==n-1]);
// for(uint i=0;i<n;i++)GetVal[1][i].print(),putchar(" \n"[i==n-1]);
// for(uint i=0;i<n;i++)GetVal[2][i].print(),putchar(" \n"[i==n-1]);
modint ans;
for(uint i=0;i<n;i++)ans+=(GetVal[0][i]*GetVal[2][i])^k;
for(uint i=1;i<n;i++)ans-=(GetVal[1][i]*(GetVal[2][i]-1))^k;
ans.println();
return 0;
}
// 那就是希望。
// 即便需要取模,也是光明。
c