树同构
前置知识:图的遍历,树的重心。
树同构是一种快速判断两棵树是否本质相同的算法。这里本质相同在不同种类的树中有不同定义。
有标号树的判定是好做的。对于有标号有根树,我们从根节点开始
AHU 树同构
有根树
我们考虑无标号有根树怎么做。我们有
-
- 递归
u 的子树。 -
比如,以下一棵树:
其括号序为:
这是对于有标号树有根树的定义。对于无根树,我们改为在初次进入时加入
- 为了不让括号序受输入顺序的影响,在拼接儿子答案时,要从字典序从小到大拼接。
:::
:::info[参考实现]
string ahu(int u,int fath) { int v,cnt=0,i; string nw,a[60]; nw="0"; for(i=0;i<s[u].size();i++) { v=s[u][i]; if(v==fath) continue; cnt++; a[cnt]=ahu(v,u); } sort(a+1,a+cnt+1); for(i=1;i<=cnt;i++) nw+=a[i]; nw+="1"; return nw; }::: 对于无标号有根树,我们比较该函数返回值即可,时间复杂度
\text{O} (T n \log n) ,其中T 为树的数量。无根树
我们考虑无标号无根树怎么做,也就是这道题:【模板】树同构([BJOI2015]树的同构)。
无根树一般考虑钦定根。寻找树上与标号无关的特征点,常见的是重心。于是我们找出树中的重心,钦定它为根,套用无根树做法即可。
注意一棵树可能有两个重心,我们取二者答案中字典序较大的那个。 :::info[参考实现]
maxsz[0]=n;
getsz(1,0);
rt=getrt(1,0,n);
for(j=1;j<=n;j++)
{
if(maxsz[j]==maxsz[rt])
ans[i]=max(ans[i],ahu(j,0));
}
:::
比较两棵树的
树同构应用较少,故不给出题单。