题解:P16355 「Diligent-OI R3 C」彼方へ、名もなき海辺より
FHY_patrickpp · · 题解
赛时一发过了说是。
题面描述的很清楚了。在此不过多描述。
每个节点恰好选一条边,故总边数为
因此,连通块个数就是环的个数。
我们可以看全集为所有可能的选择方案,方案总数:
其中
对于每个节点
考虑以
定义
其中
按照后序遍历(从叶子向上)计算
综上可得知总方案数为
时间复杂度
#include<bits/stdc++.h>
using namespace std;
const int MOD=998244353;
const int N=500005;
int n,deg[N],S[N];
vector<int> g[N];
int dep[N],pa[N],order[N],cnt;
int qpow(int a,int b){
int r=1;
for(;b;b>>=1,a=1LL*a*a%MOD) if(b&1) r=1LL*r*a%MOD;
return r;
}
void dfs(int u,int f){
pa[u]=f; dep[u]=dep[f]+1;
for(int v:g[u]) if(v!=f){
deg[u]++; // 儿子数
dfs(v,u);
}
}
void bfs(){
queue<int> q; q.push(1); cnt=0;
while(!q.empty()){
int u=q.front(); q.pop();
order[++cnt]=u;
for(int v:g[u]) if(v!=pa[u]) q.push(v);
}
}
int main(){
ios::sync_with_stdio(0); cin.tie(0);
cin>>n;
for(int i=1;i<n;i++){
int u,v; cin>>u>>v;
g[u].push_back(v);
g[v].push_back(u);
}
dep[0]=-1; dfs(1,0);
// 度数 = 儿子数 + 深度 (根深度0)
for(int i=1;i<=n;i++) deg[i] += dep[i];
int M=1;
for(int i=1;i<=n;i++) M=1LL*M*deg[i]%MOD;
// 预处理逆元
vector<int> inv(n+1);
for(int i=1;i<=n;i++) inv[i]=qpow(deg[i],MOD-2);
bfs();
// 逆序处理即从叶子向上
for(int i=n;i>=1;i--){
int u=order[i];
int sum=0;
for(int v:g[u]) if(v!=pa[u]){
sum = (sum + inv[v] + S[v]) % MOD;
}
S[u] = 1LL * sum * inv[u] % MOD;
}
int E=0;
for(int i=1;i<=n;i++) E=(E+S[i])%MOD;
int ans=1LL*M*E%MOD;
cout<<ans<<'\n';
return 0;
}