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;
}
posted @ 2023-11-09 21:39  zifanwang  阅读(3)  评论(0编辑  收藏  举报  来源