非常巧妙的题目。

首先对于一棵树,总是有 $|V| - |E| = 1$。故对于一个森林 $|V| - |E|$ 等于连通块数。

故所求即为:$(|V_1| - |E_1|) \cdot (|V_2|-|E_2|) = |V_1||V_2| - |V_1||E_2| - |E_1||V_2| + |E_1||E_2|$。

我们考虑分别计算:

  • $|V_1||V_2|$:在一棵树中选择 $u$,另一棵树中选择 $v \not = u$,概率均为 $\frac{1}{2}$,故 $|V_1||V_2| = \frac{n(n-1)}{4}$。
  • $|V_1||E_2|$:在一棵树中选择 $(u,v)$,另一棵树中选择 $w \not = u \not = v$,概率均为 $\frac{1}{2}$,故 $|V_1||E_2| = \frac{(n-1)(n-2)}{8}$。
  • $|E_1||V_2|$:与 $|V_1||E_2|$ 相同。
  • $|E_1||E_2|$:在一棵树中枚举 $(u,v)$,在另一颗树中选择 $(x,y)$,并 $u \not = v \not = x \not = y$。需要统计另一颗树中 $u$,$v$ 的度 $dg(u)$,$dg(v)$,与是否存在边 $find(u,v)$。那么 $|E_1||E_2| = \sum_{(u,v)} n - 1 - dg(u) - dg(v) + find(u,v)$。一个简单的统计,每个点概率均为 $\frac{1}{2}$。

然后就做完了,非常巧妙。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxn=2e5;
const int mod=998244353;
const int inv2=499122177;
const int inv4=inv2*inv2%mod;
const int inv16=inv4*inv4%mod;
int n,ans;
int dg[maxn+5];
unordered_map<int,bool> E[maxn+5];
inline int Fpow(int x,int y){
int t=1;
for(;y;y>>=1,x=1ll*x*x%mod)
if(y&1) t=1ll*t*x%mod;
return t;
}
signed main(){
freopen("tree.in","r",stdin);
freopen("tree.out","w",stdout);
int u,v;
scanf("%lld",&n);
for(int i=1;i<n;i++){
scanf("%lld%lld",&u,&v);
E[u][v]=E[v][u]=1;
dg[u]++,dg[v]++;
}
for(int i=1;i<n;i++){
scanf("%lld%lld",&u,&v);
ans=(ans+(n-1)-dg[u]-dg[v]+E[u][v])%mod;
}
ans=ans*inv16%mod;
ans=(ans+n*(n-1)%mod*inv4%mod)%mod;
ans=(ans-(n-1)*(n-2)%mod*inv4%mod)%mod;
printf("%lld",(ans+mod)%mod);
return 0;
}