1 条题解
-
1
考虑异或和的二进制下的一的个数有什么性质。
设 表示 二进制下一的个数的奇偶性,那么会发现一个有趣的性质。
我们发现这个东西满足异或的性质,所以设 表示 到 链上的异或和的一的个数奇偶性。
那么可以得到 。
然后可以发现 要么是 ,要么是 ,约束条件实际上约束了 和 。
直接扩展域并查集就好了。
代码
#include<bits/stdc++.h> using namespace std; const int N=2e5+5; int _,n,m; vector<pair<int,int> > e[N]; int f[N<<1],fff; struct Ans{int x,y,s;}ans[N]; int getanc(int k){return f[k]==k?k:f[k]=getanc(f[k]);} void he(int x,int y){if(getanc(x)!=getanc(y))f[getanc(x)]=y;}//合并 bool work(int x){ bool s=1; for(;x;x>>=1)if(x&1)s=!s; return s; } void dfs(int x,int fa){ for(auto i:e[x]){ int y=i.first,z=i.second; if(y==fa)continue; if(z!=-1){ if(work(z))he(x,y),he(x+n,y+n); else he(x,y+n),he(x+n,y); } dfs(y,x); } } int main(){ scanf("%d",&_); while(_--){ int ff=0; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)e[i].clear(); for(int i=1;i<=2*n;i++)f[i]=i; for(int i=1,x,y,z;i<n;i++){ scanf("%d%d%d",&x,&y,&z); e[x].emplace_back(y,z); e[y].emplace_back(x,z); ans[i]=(Ans){x,y,z}; } dfs(1,0); for(int i=1,x,y,p;i<=m;i++){ scanf("%d%d%d",&x,&y,&p); if(p==1){ if(getanc(x)==getanc(y)||getanc(x+n)==getanc(y+n))ff=1; he(x,y+n),he(y,x+n); } else{ if(getanc(x)==getanc(y+n)||getanc(x+n)==getanc(y))ff=1; he(x,y),he(y+n,x+n); } } if(ff)puts("NO"); else{ puts("YES"); for(int i=1;i<n;i++){ if(ans[i].s==-1){ if(getanc(ans[i].x)==getanc(ans[i].y)||getanc(ans[i].x+n)==getanc(ans[i].y+n))ans[i].s=0; else{ ans[i].s=1; he(ans[i].x,ans[i].y+n); he(ans[i].x+n,ans[i].y); } } printf("%d %d %d\n",ans[i].x,ans[i].y,ans[i].s); } } } }
- 1
信息
- ID
- 63
- 时间
- 2000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者