解题思路:
先考虑根是否可行,即步数是否能抵消完。
考虑
w[x]
w
[
x
]
表示
x
x
的子树内最少的消剩下的点数。
观察发现,最难消的肯定是最大的儿子,设为
y
y
,而且如果 能被消完,即
others=size[x]−1−size[y]>=w[y]
o
t
h
e
r
s
=
s
i
z
e
[
x
]
−
1
−
s
i
z
e
[
y
]
>=
w
[
y
]
,那么
w[x]
w
[
x
]
最多在
size[x]
s
i
z
e
[
x
]
为奇数时剩一个子节点没被消,否则肯定能消完(除了自己)。
如果
y
y
不能被消完,那么。
再考虑每个节点是否合法。
其实思路就比较简单了,将根到
x
x
的路径当做新根(根肯定能走到,且不影响路径上的子树),用与上面类似的方法判断即可。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll getint()
{
ll i=0,f=1;char c;
for(c=getchar();(c!='-')&&(c<'0'||c>'9');c=getchar());
if(c=='-')c=getchar(),f=-1;
for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';
return i*f;
}
const int N=100005;
int W,n;
int size[N],dep[N],w[N],mx1[N],mx2[N],dp[N],ans[N];
int tot,first[N],nxt[N<<1],to[N<<1];
void add(int x,int y)
{
nxt[++tot]=first[x],first[x]=tot,to[tot]=y;
}
void dfs1(int u,int fa)
{
size[u]=1,dep[u]=dep[fa]+1,mx1[u]=mx2[u]=0;
for(int e=first[u];e;e=nxt[e])
{
int v=to[e];if(v==fa)continue;
dfs1(v,u),size[u]+=size[v];
if(size[v]>size[mx1[u]])mx2[u]=mx1[u],mx1[u]=v;
else if(size[v]>size[mx2[u]])mx2[u]=v;
}
if(size[u]-1-size[mx1[u]]>=w[mx1[u]])w[u]=(size[u]-1)%2;
else w[u]=w[mx1[u]]-(size[u]-1-size[mx1[u]]);
w[u]++;
}
void dfs2(int u,int fa)
{
ans[u]=0;
if((size[1]-dep[u])%2==0)
{
int v=dp[u];if(size[v]<size[mx1[u]])v=mx1[u];
if(size[1]-dep[u]-size[v]>=w[v])ans[u]=1;
}
for(int e=first[u];e;e=nxt[e])
{
int v=to[e];if(v==fa)continue;
dp[v]=dp[u];
if(v!=mx1[u]&&size[mx1[u]]>size[dp[v]])dp[v]=mx1[u];
else if(size[mx2[u]]>size[dp[v]])dp[v]=mx2[u];
dfs2(v,u);
}
}
void solve()
{
tot=0;memset(first,0,sizeof(first));
n=getint();
for(int i=1;i<n;i++)
{
int x=getint(),y=getint();
add(x,y),add(y,x);
}
dfs1(1,0);
dp[1]=0,dfs2(1,0);
if(W==3)putchar('0'+ans[1]);
else for(int i=1;i<=n;i++)putchar('0'+ans[i]);
putchar('\n');
}
int main()
{
//freopen("lx.in","r",stdin);
W=getint();for(int T=getint();T;T--)solve();
return 0;
}