1. 程式人生 > 其它 >#Trie#洛谷 7717 「EZEC-10」序列

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

Trie

題目


分析

考慮這些關係可以用若干個連通塊表示,而可以用一個數異或邊權表示,
那麼每個連通塊有一個生成樹,而判斷非樹邊是否合法即可,
那麼問題就轉換成有多少個數異或任意一個元素均不大於\(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);
}