Hemose on the Tree
https://codeforces.com/contest/1670/problem/E
理论
总共有2p个点,2p-1个边,那么总的赋值点最大为2(p+1)-1,所以换算为2进制,最高位为2p
n为2^p
2p的左右两边各有2p-1个数,每个数都有对应的数,如a和an,将这两个数赋值可以发现最后对结果的影响只是n
考虑是给点赋值小的数,还是给边赋值小的数
如果前面的异或和=n,那么给边赋值大的,防止过程中值超过n,后给点赋值小的
如果前面的异或和=0,那么给边赋值小的,防止过程中值超过n,后给点赋值大的
如p=2时
总赋值有 1 2 3 4 5 6 7
1和7,2和6,3和7都要成对赋值,赋值在一条边和边上的点上
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define F(i, a, b) for(int i = a; i <= (b); ++i)
#define F2(i, a, b) for(int i = a; i < (b); ++i)
#define dF(i, a, b) for(int i = a; i >= (b); --i)
#define pb push_back
#define pf push_front
#define fi first
#define sc second
#define inf 0x3f3f3f3f
#define mod 998244353
#define infll 0x3f3f3f3f3f3f3f3f
#define mkp make_pair
const int N=3e5+7;
struct li{
int to,next,num;
}line[6*N];
int cnt;
int head[N];
void addline(int u,int v,int x){
line[++cnt]={v,head[u],x};
head[u]=cnt;
}
int na[N],nb[N];
int tot;
int p,n;
void dfs(int x,int fa,bool flag){
for(int i=head[x];i;i=line[i].next){
int to=line[i].to;
int num=line[i].num;
if(to!=fa){
int a=++tot;
int b=a^n;
if(flag) swap(a,b);
na[to]=a;
nb[num]=b;
dfs(to,x,!flag);
}
}
}
void solve(){
scanf("%d",&p);
n=1<<p;
F(i,1,n) head[i]=0;
cnt=tot=0;
F(i,1,n-1) {
int u,v;
scanf("%d%d",&u,&v);
addline(u,v,i);
addline(v,u,i);
}
na[1]=n;
dfs(1,0,0);
printf("1\n");
F(i,1,n) printf("%d%c",na[i],i==n?'\n':' ');
F(i,1,n-1) printf("%d%c",nb[i],i==n-1?'\n':' ');
}
int main(){
//freopen("C:\\Users\\86155\\Desktop\\1.in","r",stdin);
//freopen("C:\\Users\\86155\\Desktop\\1.out","w",stdout);
int t=1;
scanf("%d",&t);
while(t--){
solve();
}
return 0;
}