1. 程式人生 > >【樹hs】[BJOI2015]樹的同構

【樹hs】[BJOI2015]樹的同構

題目描述
樹是一種很常見的資料結構。 我們把N個點,N-1條邊的連通無向圖稱為樹。 若將某個點作為根,從根開始遍歷,則其它的點都有一個前驅,這個樹就成為有根樹。 對於兩個樹T1和T2,如果能夠把樹T1的所有點重新標號,使得樹T1和樹T2完全相 同,那麼這兩個樹是同構的。也就是說,它們具有相同的形態。 現在,給你M個有根樹,請你把它們按同構關係分成若干個等價類。

輸入格式
第一行,一個整數M。 接下來M行,每行包含若干個整數,表示一個樹。第一個整數N表示點數。接下來N 個整數,依次表示編號為1到N的每個點的父親結點的編號。根節點父親結點編號為0。

輸出格式
輸出M行,每行一個整數,表示與每個樹同構的樹的最小編號。

樣例一
input

4 4 0 1 1 2 4 2 0 2 3 4 0 1 1 1 4 0 1 2 3 output 1 1 3 1 樣例解釋 編號為1, 2, 4 的樹是同構的。編號為3 的樹只與它自身同構。 限制與約定 對於100%的資料,1≤N,M≤501≤N,M≤50 時間限制:1s1s 空間限制:256MB
T

這道題是樹hs裸題,樹hs的思路就是,先把每個節點的點權賦為1,然後父節點累加子節點平方和自己的值向上返回,

就是一個遞迴的過程,然後自然溢位

但是每個樹的根節點可能會不同,所以我們要有對於每個樹選根的唯一標準

對,就是樹重心,一個樹可能有多個重心,那麼我們只需要一個超級原點就ok 了

最後比較超級原點的hs值,就能知道是否同構

有一點玄學的地方,就是用seed的方式過不了,也不知道是為什麼

 1 #include<bits/stdc++.h>
 2 #define N 100
 3 #define clear(a,val) memset(a,val,sizeof(a))
 4 using namespace std;
 5 typedef unsigned long long ult;
 6 int n,m,f,cnt=1,pp;
 7 int head[N],nxt[N*2],to[N*2],size[N],ans[N];
 8 ult vv[N],val[N];
9 inline void add(int u,int v) 10 {nxt[cnt]=head[u],to[cnt]=v,head[u]=cnt++;} 11 inline void cl(){ 12 clear(size,0),clear(ans,0),clear(head,-1),cnt=1,pp=0; 13 } 14 int dfs(int now,int fa) 15 { 16 size[now]=1;int ma=-1; 17 for(int i=head[now];i!=-1;i=nxt[i]) 18 { 19 int t=to[i]; 20 if(t==fa)continue; 21 size[now]+=dfs(t,now); 22 ma=max(ma,size[t]); 23 } 24 ma=max(ma,n-size[now]); 25 if(ma<=(n>>1))ans[++pp]=now; 26 return size[now]; 27 } 28 inline void weigh() 29 { 30 dfs(1,-1); 31 for(int i=1;i<=pp;i++) 32 add(n+1,ans[i]); 33 } 34 ult cal(int now,int fa) 35 { 36 vv[now]=1; 37 for(int i=head[now];i!=-1;i=nxt[i]) 38 { 39 int t=to[i]; 40 if(t==fa)continue; 41 vv[now]+=cal(t,now); 42 } 43 return vv[now]*vv[now]; 44 } 45 inline void init_build_weigh_solve() 46 { 47 clear(head,-1); 48 scanf("%d",&m); 49 for(int i=1;i<=m;i++) 50 { 51 cl(); 52 scanf("%d",&n); 53 for(int j=1;j<=n;j++) 54 { 55 scanf("%d",&f); 56 if(f==0)continue; 57 else add(f,j),add(j,f); 58 } 59 weigh(); 60 val[i]=cal(n+1,-1); 61 } 62 for(int i=1;i<=m;i++) 63 { 64 for(int j=1;j<=i;j++) 65 { 66 if(val[i]==val[j]) 67 { 68 printf("%d\n",j); 69 break; 70 } 71 } 72 } 73 } 74 int main() 75 { 76 init_build_weigh_solve(); 77 return 0; 78 }