非常巧妙的题目。
首先对于一棵树,总是有 $|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; }
|