CF1067E Random Forest Rank 题解
矩阵的秩,即选出 \(k\) 行和 \(k\) 列使得这些行和列的交点组成的行列式的值不为 \(0\),满足条件的最大的 \(k\)。
考虑一个森林的邻接矩阵的秩的意义,根据行列式的值的定义可以得到其为该森林中的最大匹配的点数(选出若干条边,使得不同的边不共点,边的个数乘二)。
考虑怎么求一个森林的最大匹配的点数。可以贪心,从每棵树的叶子节点开始,如果父亲节点还没被匹配就将其与父亲节点匹配。
然后直接在树上 DP,对每个点求出该点与其一儿子匹配的概率,转移很简单。答案即为所有点在上述 DP 中的值的和。
时间复杂度 \(O(n)\)。
参考代码:
#include<bits/stdc++.h>
#define ll long long
#define mxn 500003
#define md 998244353
#define pb push_back
using namespace std;
int n,ans;
ll d,f[mxn];
vector<int>g[mxn];
void dfs(int x,int fa){
f[x]=1;
for(int i:g[x])if(i!=fa){
dfs(i,x);
f[x]=((1-f[i])+f[i]*499122177ll)%md*f[x]%md;
}
ans=(ans+1-f[x])%md;
}
signed main(){
scanf("%d",&n);
d=1;
for(int i=1,x,y;i<n;++i){
scanf("%d%d",&x,&y);
g[x].pb(y),g[y].pb(x);
d=d*2%md;
}
dfs(1,0);
cout<<(ans*2%md+md)%md*d%md;
return 0;
}