树同构
树同构是树哈希与换根 dp 的结合。
树哈希是哈希中的一个种类,这里先给出哈希函数:
这里使用 unsigned long long
的自然溢出特性代替取模。
我们设
直接使用上式计算即可。
再设
易知:
贴个代码:
#include<bits/stdc++.h> #define int unsigned long long using namespace std; int rp; const int N=1e3+10; int g[N],f[N]; struct edge{ int v,next; }edges[N*2]; int head[N],idx; set<int>s[N]; int n; void add_edge(int u,int v){ idx++; edges[idx].v=v; edges[idx].next=head[u]; head[u]=idx; return; } int xor_shift(int x){ x^=rp; x^=x<<13; x^=x>>7; x^=x<<17; x^=rp; return x; } void init(){ idx=0; for(int i=1;i<=n;i++)head[i]=0; return; } void get_hash_val(int u,int fa){ g[u]=1; for(int i=head[u];i;i=edges[i].next){ int v=edges[i].v; if(v==fa)continue; get_hash_val(v,u); g[u]+=xor_shift(g[v]); } return; } void dfs(int u,int fa){ if(fa==0){ f[u]=g[u]; } else{ f[u]=xor_shift(f[fa]-xor_shift(g[u]))+g[u]; } for(int i=head[u];i;i=edges[i].next){ int v=edges[i].v; if(v==fa)continue; dfs(v,u); } return; } signed main(){ std::ios::sync_with_stdio(false); srand(time(NULL)); rp=rand();rp++; int t; cin>>t; for(int i=1;i<=t;i++){ cin>>n; init(); int root=0; for(int j=1;j<=n;j++){ int x; cin>>x; if(x!=0){ add_edge(x,j); add_edge(j,x); } else root=j; } assert(root); get_hash_val(root,0); dfs(root,0); int ans=i; for(int j=1;j<=n;j++)s[i].insert(f[j]); for(int j=1;j<=n;j++){ for(int k=1;k<t;k++){ if(s[k].count(f[j])){ ans=min(k,ans); } } } cout<<ans<<endl; } return 0; }
本文作者:Little_corn
本文链接:https://www.cnblogs.com/little-corn/p/18157421
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步