版权声明:虽然博主很菜,但是还是请注明出处(我觉得应该没人偷我的博客) https://blog.csdn.net/qq_43346903/article/details/89036151
分析:假设现在心在位置
,则心可以通过
的不同子树的生长抵消移动,仍然停留在
位置
当然也有无法停留在
位置的情况:
第一种是
为奇数,显然多出一次生长
第二种是
最大的子树的
过于大(大于1/2),所以一定会把心拉到里面去
那么我们就可以树形DP判断根节点是否可行了,设
表示以
为根的子树可以把外面的心往这边拉多少距离,很好处理
然后考虑从根节点扩展答案,设当前扩展到
,考虑能不能把心从根弄到
去
设
到
的路径长度dep[y],当
为奇数时,不行,这表示除了这条路径的其他点无法抵消完全
那么如果为偶数,就把
的路径看成一个点就完了
Code:
#include<bits/stdc++.h>
#define mod 998244353
#define N 300005
#define rt 1
using namespace std;
inline int read(){
int ans=0;
char ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
return ans;
}
int W,t,n,cnt=0,siz[N],first[N],mx1[N],mx2[N],dep[N],f[N],w[N],ans[N];
struct edge{int v,next;}e[N<<1];
inline void add(int u,int v){e[++cnt].v=v,e[cnt].next=first[u],first[u]=cnt;}
inline void dfs1(int p,int fa){
siz[p]=1,mx1[p]=mx2[p]=0;
for(int i=first[p];i;i=e[i].next){
int v=e[i].v;
if(v==fa)continue;
dep[v]=dep[p]+1,dfs1(v,p),siz[p]+=siz[v];
if(siz[mx1[p]]<siz[v])mx2[p]=mx1[p],mx1[p]=v;
else if(siz[mx2[p]]<siz[v])mx2[p]=v;
}
if(siz[p]-1>=siz[mx1[p]]+w[mx1[p]])w[p]=(siz[p]-1)%2;
else w[p]=w[mx1[p]]-(siz[p]-1-siz[mx1[p]]);
++w[p];
}
inline void dfs2(int p,int fa){
ans[p]=0;
if((siz[rt]-dep[p])%2==0){
int v=f[p];
if(siz[v]<siz[mx1[p]])v=mx1[p];
if(siz[rt]-dep[p]-siz[v]-w[v]>=0)ans[p]=1;
}
for(int i=first[p];i;i=e[i].next){
int v=e[i].v;
if(v==fa)continue;
f[v]=f[p];
if(v!=mx1[p]&&siz[mx1[p]]>siz[f[v]])f[v]=mx1[p];
else if(siz[mx2[p]]>siz[f[v]])f[v]=mx2[p];
dfs2(v,p);
}
}
int u,v;
int main(){
W=read(),t=read();
while(t--){
n=read(),cnt=0,memset(first,0,sizeof(first));
for(int i=1;i<n;++i)u=read(),v=read(),add(u,v),add(v,u);
dep[1]=1,dfs1(1,1),f[1]=0,dfs2(1,1);
if(W==3)putchar(ans[1]^48);
else for(int i=1;i<=n;++i)putchar(ans[i]^48);
puts("");
}
return 0;
}