Treelabeling
结论:每个点都能是必胜点,最高位的1在相同位子则能走,否则不能走
那么可以按1的最高位子来处理(最高位的1在相同位子的进行分堆) ,对树奇偶染色,同一堆的不能分开放
//#pragma GCC optimize(2)
//#pragma GCC optimize(3,"Ofast","inline")
#include<bits/stdc++.h>
#define int long long
#define fi first
#define se second
#define pb push_back
#define pii pair<int,int>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
const int inf=8e18;
const int maxn=2e5+100;
int col[maxn];
int ans[maxn];
vector<int>g[maxn];
vector<int>v[2];
void dfs(int x,int f)
{
for(auto it:g[x])
{
if(it==f)continue;
col[it]=col[x]^1;
v[col[it]].pb(it);
dfs(it,x);
}
}
signed main()
{
IOS
int tt;
cin>>tt;
while(tt--)
{
priority_queue<pii>q;
int n;
cin>>n;
for(int i=1; i<n; i++)
{
int x,y;
cin>>x>>y;
g[x].pb(y);
g[y].pb(x);
}
v[0].pb(1);
dfs(1,-1);
for(int i=0;; i++)
{
int l=1<<i;
int r=(1<<(i+1))-1;
if(r<n) q.push({r-l+1,l});
else
{
q.push({n-l+1,l});
break;
}
}
int l=0,r=0;
while(!q.empty())
{
if(v[0].size()-l>v[1].size()-r)
{
auto now=q.top();
for(int i=l; i<l+now.fi; i++)
{
ans[v[0][i]]=now.se+i-l;
}
l+=now.fi;
}
else
{
auto now=q.top();
for(int i=r; i<r+now.fi; i++)
{
ans[v[1][i]]=now.se+i-r;
}
r+=now.fi;
}
q.pop();
}
for(int i=1; i<=n; i++)
{
cout<<ans[i]<<" ";
}
cout<<"\n";
for(int i=1; i<=n; i++)
{
g[i].clear();
col[i]=0;
ans[i]=0;
}
v[0].clear();
v[1].clear();
}
}