CF1624G MinOr Tree 题解

CF1624G MinOr Tree

给定 \(n\) 个点,\(m\) 条边,求在或运算小的最小生成树

考虑二进制拆位,从高位玩往地位贪心,如果答案第 \(i\) 位可以为 \(0\),后 \(i-1\) 取值无论是多少都比第 \(i\)\(1\) 更优。

因此假设当前考虑第 \(k\) 位,则我们需要判断在满足高位的情况下,第 \(k\) 位能否取到 \(0\),则假设已经确定的高位的结果为 \(x\),即应当满足 \(x|w<x+2^{k}\)

具体见代码

const int N=200005;
int n,m,fa[N];
inline int fidf(int x){return x==fa[x]?x:fa[x]=fidf(fa[x]);}
struct sgline{int u,v;ll w;}line[N];
inline bool check(ll las,ll loc){
	int cnt=0;
	for(int i=1;i<=n;++i)fa[i]=i;
	for(int i=1;i<=m;++i){
		if((line[i].w|las)>=(las+(1ll<<loc)))continue;
		int fu=fidf(line[i].u),fv=fidf(line[i].v);
		if(fu==fv)continue;
		fa[fu]=fv;
		if(++cnt==n-1)break;
	}
	return cnt==n-1;
}
int main(){
	int T=read();
	while(T--){
		n=read(),m=read();
		for(int i=1;i<=m;++i){
			line[i].u=read(),line[i].v=read();
			line[i].w=read();
		}
		ll ans=0;
		for(ll i=30;i>=0;--i){
			if(!check(ans,i))
				ans|=(1ll<<i);
		}
		printf("%lld\n",ans);
	}
	return 0;
}
posted @ 2022-10-02 22:11  BigSmall_En  阅读(83)  评论(0)    收藏  举报