[atAGC052B]Tree Edges XOR

定义两点的距离$d(x,y)$为$x$到$y$路径上边权异或和,则两棵树相同当且仅当$\forall 1\le i\le n$,$d(1,i)$相同

新建一个节点0,连边$(0,1)$,初始权值为0,且不能以这条边为对象操作(但操作与1相连的边会影响其)

记$d_{i}=d(0,i)$,考虑一次操作$(x,y)$对$d_{i}$的影响,恰好是交换$d_{x}$和$d_{y}$

最终,令$a_{i}$为目标树中$d(1,i)$的值,即要求$d_{i}\oplus d_{1}=a_{i}$

同时,记$b_{i}$为初始树中$d(0,i)$的值(也即$d(1,i)$),那么$d_{i}$即$b_{i}$重新排列的结果,有$\bigoplus_{i=1}^{n}d_{i}=\bigoplus_{i=1}^{n}b_{i}$

将之代入前者,根据$n$为奇数,可得$d_{1}=\bigoplus_{i=1}^{n}a_{i}\bigoplus_{i=1}^{n}b_{i}$,再判定$d_{1}$是否在本来的$b_{i}$中,以及$b_{i}\oplus d_{1}$是否等于$a_{i}$(排序后的结果)即可

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 100005
 4 struct Edge{
 5     int nex,to,len1,len2;
 6 }edge[N<<1];
 7 int E,n,x,y,z1,z2,head[N],a[N],b[N];
 8 void add(int x,int y,int z1,int z2){
 9     edge[E].nex=head[x];
10     edge[E].to=y;
11     edge[E].len1=z1;
12     edge[E].len2=z2;
13     head[x]=E++;
14 }
15 void dfs(int k,int fa,int s1,int s2){
16     b[k]=s1;
17     a[k]=s2;
18     for(int i=head[k];i!=-1;i=edge[i].nex)
19         if (edge[i].to!=fa)dfs(edge[i].to,k,s1^edge[i].len1,s2^edge[i].len2);
20 }
21 int main(){
22     scanf("%d",&n);
23     memset(head,-1,sizeof(head));
24     for(int i=1;i<n;i++){
25         scanf("%d%d%d%d",&x,&y,&z1,&z2);
26         add(x,y,z1,z2);
27         add(y,x,z1,z2);
28     } 
29     dfs(1,0,0,0);
30     for(int i=1;i<=n;i++)b[0]^=a[i];
31     for(int i=1;i<=n;i++)b[0]^=b[i];
32     for(int i=1;i<=n;i++)b[i]^=b[0];
33     sort(a+1,a+n+1);
34     sort(b+1,b+n+1);
35     if (b[1]){
36         printf("NO");
37         return 0;
38     }
39     for(int i=1;i<=n;i++)
40         if (a[i]!=b[i]){
41             printf("NO");
42             return 0;
43         }
44     printf("YES");
45 } 
View Code

 

posted @ 2021-04-21 22:24  PYWBKTDA  阅读(184)  评论(0编辑  收藏  举报