K. Hiding a Tree
分析:
-
发现对 a n s ans ans 造成影响的只有度为奇数的点,度为偶数的点就不用管
-
因此,我们要修改的就是度为奇数且能修改的点
-
再想一下,发现当这样的点存在三个或三个以上,直接修改这三个点即可
然后就是,考虑当这样的点的个数小于三的情况
- 为0,直接就输出-1
- 为1,要去找一个可交换值的度为偶数的点
- 为2,先看一下存不存在 ”为1“ 的情况,再判断这两个点
综上,可分为两大类:
- 先判断,存不存在能交换值的度为偶数的点
- 再特判 ”为2“ ”为3“ 的情况即可(详见代码)
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+5, base=1<<20;
int a[N],in[N],u[N],v[N];
int g[N],b[N];
signed main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<n;i++)
{
cin>>u[i]>>v[i];
in[u[i]]++; in[v[i]]++;
}
int tot=0,ans=n;
for(int i=1;i<=n;i++)
{
if(in[i]&1)
{
ans^=i;
if(a[i]) g[++tot]=i;
}
}
if(!ans)
{
cout<<n<<endl;
for(int i=1;i<n;i++) cout<<u[i]<<' '<<v[i]<<endl;
return 0;
}
for(int i=1;i<=n;i++) b[i]=i;
int fg=0;
for(int i=1;i<=tot;i++)
{
// 遍历寻找是否又满足条件的度为偶数的点
int t=ans^g[i];
if(t>n)
{
fg=1; b[g[i]]=t; break;
}
else
{
if(!a[t] || in[t]&1) continue; // 不能改或者度为奇数
swap(b[g[i]],b[t]);
fg=1; break;
}
}
if(!fg)
{
if(tot>2)
{
int t=ans^g[1]^g[2]^g[3];
b[g[1]]=base; b[g[2]]=base>>1; b[g[3]]=base+(base>>1)+t;
fg=1;
}
else if(tot==2)
{
int t=ans^g[1]^g[2];
if(t) // 当t=0时,说明这两个点要改为值为相同的点,显然不成立
{
b[g[1]]=base; b[g[2]]=base+t;
fg=1;
}
}
}
if(fg)
{
cout<<n<<endl;
for(int i=1;i<n;i++) cout<<b[u[i]]<<' '<<b[v[i]]<<endl;
}
else cout<<"-1"<<endl;
}