• 周日. 10 月 6th, 2024

5G编程聚合网

5G时代下一个聚合的编程学习网

热门标签

#Trie#洛谷 7717 「EZEC-10」序列

admin

11 月 28, 2021

题目


分析

考虑这些关系可以用若干个连通块表示,而可以用一个数异或边权表示,
那么每个连通块有一个生成树,而判断非树边是否合法即可,
那么问题就转换成有多少个数异或任意一个元素均不大于(k)
把每个点到选定的根的异或值算出来,放进Trie里判断即可


代码

#include <cstdio>
#include <cctype>
#include <algorithm>
#define rr register
using namespace std;
const int N=500011; struct node{int y,w,next;}e[N<<1];
int trie[N*30][2],n,m,k,as[N],tot,ans=1,flag,a[N],v[N];
inline signed iut(){
	rr int ans=0; rr char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
	return ans;
}
inline void BackTrace(){for (;tot;--tot) trie[tot][0]=trie[tot][1]=0; tot=1;}
inline void Insert(int x){
	rr int p=1;
	for (rr int i=29;~i;--i){
		rr int z=(x>>i)&1;
		if (!trie[p][z]) trie[p][z]=++tot;
		p=trie[p][z];
	}
}
inline signed dfs2(int p,int i,int now){
	rr int t=trie[p][!trie[p][0]];
	if (trie[p][0]&&trie[p][1])
		return dfs2(trie[p][0],i-1,now|(1<<i))+dfs2(trie[p][1],i-1,now|(1<<i));
	else if (t) return ((now|(1<<i))>k)?dfs2(t,i-1,now):(dfs2(t,i-1,now|(1<<i))+(1<<i));
	    else return now<=k;
}
inline void dfs1(int x){
	v[x]=1,Insert(a[x]);
	for (rr int i=as[x];i;i=e[i].next){
		if (flag) return;
		if (v[e[i].y]){
			if ((a[x]^e[i].w)!=a[e[i].y])
			    {flag=1; return;}
		}else a[e[i].y]=a[x]^e[i].w,dfs1(e[i].y);
	}
}
signed main(){
	n=iut(),m=iut(),k=iut();
	for (rr int i=1;i<=m;++i){
		rr int x=iut(),y=iut(),w=iut();
		e[i<<1]=(node){y,w,as[x]},as[x]=i<<1;
		e[i<<1|1]=(node){x,w,as[y]},as[y]=i<<1|1;
	}
	for (rr int i=1;i<=n;++i)
	if (!v[i]){
		BackTrace(),flag=0,dfs1(i);
		if (flag) return !printf("0");
		ans=1ll*ans*dfs2(1,29,0)%1000000007;
	}
	return !printf("%d",ans);
}

发表回复