【樹hs】[BJOI2015]樹的同構
阿新 • • 發佈:2019-01-01
題目描述 樹是一種很常見的資料結構。 我們把N個點,N-1條邊的連通無向圖稱為樹。 若將某個點作為根,從根開始遍歷,則其它的點都有一個前驅,這個樹就成為有根樹。 對於兩個樹T1和T2,如果能夠把樹T1的所有點重新標號,使得樹T1和樹T2完全相 同,那麼這兩個樹是同構的。也就是說,它們具有相同的形態。 現在,給你M個有根樹,請你把它們按同構關係分成若干個等價類。 輸入格式 第一行,一個整數M。 接下來M行,每行包含若干個整數,表示一個樹。第一個整數N表示點數。接下來N 個整數,依次表示編號為1到N的每個點的父親結點的編號。根節點父親結點編號為0。 輸出格式 輸出M行,每行一個整數,表示與每個樹同構的樹的最小編號。 樣例一 inputT4 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
這道題是樹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 }