【bzoj 4337】樹的同構
阿新 • • 發佈:2019-01-24
解題思路
樹同構模板題。
為了保險用了雙雜湊。
選了極其暴力的方法處理兩個重心的情況:對於每個重心分別求雜湊值然後取max。
雜湊的時候,每次將所有子節點的雜湊值排好序拿出來,然後看心情瞎搞,隨便乘一乘模一模,最後將根節點的雜湊值作為整棵樹的雜湊值。
程式碼:
#include<algorithm>
#include<iostream>
#include<cmath>
#include<cstring>
#include<string>
#include<cstdio>
#include<cstdlib>
using namespace std;
struct tree{
int hed[55],nex[105],lb[105];
int w1[55][55],w2[55][55];
int h1[55],h2[55],ha1,ha2;
int u[5],n,root,tot,lo;
void add(int x,int y){
lo++;
nex[lo]=hed[x];
hed[x]=lo;
lb[lo]=y;
}
void read(){
int x;
memset (hed,0,sizeof(hed));
ha1=ha2=tot=lo=0;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&x);
if(!x) root=i;
else {add(x,i);add(i,x);}
}
}
int getu(int x,int fa){
int siz=1,flag=0;
for(int i=hed[x];i!=0 ;i=nex[i])
if(lb[i]!=fa){
int r0=getu(lb[i],x);
if(r0*2>n) flag=1;
siz+=r0;
}
if((n-siz)*2>n) flag=1;
if(!flag) u[++tot]=x;
return siz;
}
void ha(int x,int fa){
h1[x]=17;h2[x]=59;
int len=0;
for(int i=hed[x];i!=0;i=nex[i])
if(lb[i]!=fa){
ha(lb[i],x);len++;
w1[x][len]=h1[lb[i]];
w2[x][len]=h2[lb[i]];
}
if(!len) return ;
sort(w1[x]+1,w1[x]+len+1);
sort(w2[x]+1,w2[x]+len+1);
for(int i=1;i<=len;i++) h1[x]=(h1[x]*19260%817+w1[x][i]*17%233)%1777;
for(int i=1;i<=len;i++) h2[x]=(h2[x]*83374%294+w2[x][i]*40%332)%1443;
}
void solve(){
read();
int r=getu(root,root);
for(int i=1;i<=tot;i++){
ha(u[i],u[i]);
ha1=max(ha1,h1[u[i]]);
ha2=max(ha2,h2[u[i]]);
}
}
bool operator == (const tree p) const{
return (ha1==p.ha1 && ha2==p.ha2);
}
}T[55];
int m;
int main(){
scanf("%d",&m);
for(int i=1;i<=m;i++) T[i].solve();
for(int i=1;i<=m;i++)
for(int j=1;j<=m;j++)
if(T[i]==T[j]) {printf("%d\n",j);break;}
return 0;
}