CF1615D X(or)-mas Tree


\(Link\)

题意:给定一棵 \(n\) 个点的无根树,每条边有边权。若边权为 \(-1\) 则边权暂定。

然后有 \(m\) 条限制条件,每个条件给出形式为 \((u,v,w)\),表示将 \(u\)\(v\) 最短路径上的边权异或起来,用二进制写出后 \(1\) 的个数的奇偶性

然后构造一种方案,把所有边权确定下来,要求满足所有限制。

(碎碎念:赛时没看到\(1\) 的个数的奇偶性,还以为是憨憨题,然后就GG惹。。。)

\(Solution:\)

首先我们能发现一个性质:

\[popcount(x \oplus y) \equiv popcount(x) \oplus popcount(y)\ (\text{mod}\ 2) \]

挺易证的吧应该。

然后我们钦定 \(1\) 是根。

\(a_i\) 为从 \(1\)\(i\) 的路径上异或起来的值的 \(popcount\)

于是对于每组 \((u,v,w)\)\(w\) 就等于 \(a_u \oplus a_v\)

然后对于原有的有边权的边 \((U,V,W)\),可以看做是另一条限制 \((U,V,popcount(W)\mod 2)\)

现在我们吧这些限制当做一张无向图的边,则我们现在要给图上的每个点 \(i\) 赋一个点权(即 \(a_i\))。满足对于所有边 \((u,v,w)\)\(a_u \oplus a_v =w\)

于是我们从 \(1\) 开始(因为 \(a_1\) 一定是 \(0\))dfs 染色,遇到冲突了就是不行。

然后对于每条原来那棵树上的每条边 \((u,v)\),如果有边权就输出边权,要么输出 \(a_u \oplus a_v\)

\(Code:\)

// Problem: D. X(or)-mas Tree
// Contest: Codeforces Global Round 18
// URL: https://codeforces.com/contest/1615/problem/D
// Memory Limit: 256 MB
// Time Limit: 2000 ms
// Author: jimmyywang
// 

#include
using namespace std;
#define ll long long
#define f(i,a,b) for(ll i=a;i<=b;i++)
#define wt int tt=d;while(tt--)
#define py puts("YES")
#define pn puts("NO")
#define fe(i,e) for(int i=0;i
inline ll rd() {
	ll x=0,f=1;
	char c=getchar();
	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
	while(isdigit(c))x=x*10+c-'0',c=getchar();
	return x*f;
}
#define d rd()
#define pb push_back
const ll N=600010;
struct edge{ll v,w,nx;}e[N<<1];
ll hd[N],cnt=1;
void add(ll u,ll v,ll w){e[++cnt]=(edge){v,w,hd[u]};hd[u]=cnt;}
ll qp(ll a,ll b,ll p){
	ll ans=1;while(b){
		if(b&1)ans=ans*a%p;
		a=a*a%p;b>>=1;
	}return ans;
}ll t,n,m;
vector > ee[200010];
struct node{
	ll x,y,z;
}a[200010];
bool now[200010];
bool vis[200010];
bool flg;
#define mp make_pair
#define pop __builtin_popcount
void dfs(ll u,ll fa,ll p){if(flg)return;
	now[u]=p;vis[u]=1;
	for(int i=hd[u];i;i=e[i].nx){
		ll v=e[i].v;if(v==fa)continue;
		if(vis[v]){
			if((now[v]^now[u])!=e[i].w){flg=1;return;}
			continue;
		}dfs(v,u,p^e[i].w);
	}
}void Dfs(ll u,ll fa){
	fe(i,ee[u]){
		ll v=ee[u][i].first;
		if(v==fa)continue;
		printf("%lld %lld ",u,v);
		if(ee[u][i].second==-1)printf("%lld\n",now[u]^now[v]);
		else printf("%lld\n",ee[u][i].second);
		Dfs(v,u);
	}
}
int main(){
	wt{
		n=d,m=d;
		f(i,1,n)hd[i]=0,ee[i].clear();cnt=1;
		f(i,1,n-1){
			ll u=d,v=d,w=d;
			ee[u].pb(mp(v,w)),ee[v].pb(mp(u,w));
			if(w!=-1)add(u,v,(bool)(pop(w)&1)),add(v,u,(bool)(pop(w)&1));
		}f(i,1,m){
			ll u=d,v=d,w=d;
			add(u,v,w),add(v,u,w);
		}
		f(i,1,n)now[i]=vis[i]=0;flg=0;
		f(i,1,n)if(!vis[i])dfs(i,0,0);
		if(flg){pn;continue;}
		py;Dfs(1,0);
	}
	return 0;
}