有一个树(nn个点, n-1n−1条边的联通图),点标号从11~nn,树的边权是00或11.求离每个点最近的点个数(包括自己).
第一行一个数字TT,表示TT组数据. 对于每组数据,第一行是一个nn,表示点个数,接下来n-1n−1,每行三个整数u,v,wu,v,w,表示一条边连接的两个点和边权. T = 50,1 \leq n \leq 100000, 1 \leq u,v \leq n,0 \leq w \leq 1T=50,1≤n≤100000,1≤u,v≤n,0≤w≤1.
对于每组数据,输出答案. 考虑到输出规模过大,设ans_iansi表示第ii个点的答案.你只需输出ans_1 \ xor \ ans_2 \ xor \ ans_3.. \ xor \ ans_nans1 xor ans2 xor ans3.. xor ansn即可.
1 3 1 2 0 2 3 1
1
ans_1 = 2ans1=2 ans_2 = 2ans2=2 ans_3 = 1ans3=1 2 \ xor \ 2 \ xor \ 1=12 xor 2 xor 1=1, 因此输出11.
貌似没结束就发题解有点张扬啊 低调低调~~1A飘过
并查集再维护一个记录集合元素个数的数组,每次合并的时候更新就好啦 啦啦啦
#include <iostream> #include<cstdio> #include<cstring> using namespace std; int n,t,a[100005],num[100005],cnt; int fnd(int x) { if(x!=a[x]) a[x]=fnd(a[x]); return a[x]; } void addto(int x,int y) { x=fnd(x),y=fnd(y); if(x==y) { return ; } a[y]=a[x]; num[x]+=num[y]; return ; } int main() { // freopen("cin.txt","r",stdin); scanf("%d",&t); while(t--) { scanf("%d",&n); cnt=0; for(int i=1;i<=n;i++) {num[i]=1;a[i]=i;} for(int i=1;i<n;i++) { int u,v,q; scanf("%d%d%d",&u,&v,&q); if(q==0) addto(u,v); } //cout<<"44544"<<endl; cnt=0; for(int i=1;i<=n;i++) { if(a[i]==i&&(num[i]&1)) cnt^=num[i]; } printf("%d\n",cnt); } return 0; }