rt,看到第一篇写的很短就贺了一下
这个dsu是这样写的:一边搜索儿子v一边更新u点的set,然后若儿子更大就交换set,然后将原来u的set插入儿子的set中。若儿子的set更小就将儿子的插入u的set中
但是我想的是这样写:第一遍先求出u的重儿子,然后再来一遍进行启发式合并。
第一种写法真的对吗??感觉会不会出现问题啊
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int n;
int h[N],e[N*2],ne[N*2],idx;
int a[N],f[N];
void add(int a,int b){
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
set<int> s[N];
int son[N],cnt;
void dfs(int u,int fa){
s[u].insert(f[u]);
bool flag=0;
for(int i=h[u];~i;i=ne[i]){
int j=e[i];
if(j==fa) continue;
f[j]=f[u]^a[j];
dfs(j,u);
if(s[u].size()<s[j].size()) swap(s[u],s[j]);
for(int k:s[j])
if(s[u].count(a[u]^k))flag=1;
for(int k:s[j]) s[u].insert(k);
}
if(flag)cnt++,s[u].clear();
}
signed main(){
memset(h,-1,sizeof(h));
scanf("%d",&n);int u,v;
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<n;i++){
scanf("%d%d",&u,&v);
add(u,v);add(v,u);
}
f[1]=a[1];
dfs(1,-1);
printf("%d",cnt);
return 0;
}