1. 程式人生 > >7-1 樹的同構 (25 分)

7-1 樹的同構 (25 分)

題目 :

給定兩棵樹T1和T2。如果T1可以通過若干次左右孩子互換就變成T2,則我們稱兩棵樹是“同構”的。例如圖1給出的兩棵樹就是同構的,因為我們把其中一棵樹的結點A、B、G的左右孩子互換後,就得到另外一棵樹。而圖2就不是同構的。

圖一:

圖二:

現給定兩棵樹,請你判斷它們是否是同構的。

輸入格式:

輸入給出2棵二叉樹樹的資訊。對於每棵樹,首先在一行中給出一個非負整數N (10),即該樹的結點數(此時假設結點從0到N1編號);隨後N行,第i行對應編號第i個結點,給出該結點中儲存的1個英文大寫字母、其左孩子結點的編號、右孩子結點的編號。如果孩子結點為空,則在相應位置上給出“-”。給出的資料間用一個空格分隔。注意:題目保證每個結點中儲存的字母是不同的。

輸出格式:

如果兩棵樹是同構的,輸出“Yes”,否則輸出“No”。

思路:

這個題讀完題之後,沒有建樹,而是直接處理的樹中每個節點的左孩子與右孩子的資訊。

根據題意可以得知只要兩棵樹上每個節點的左右孩子一樣,那麼這兩棵樹就是同構。

所以,根據給出的資訊,分別存一下兩個樹的孩子資訊,然後兩棵樹相同的節點分別進行比較,最後得出結果。

程式碼:

#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define FRE() freopen("in.txt","r",stdin)
using namespace
std; typedef long long ll; struct Node { char lchild; char rchild; int idxl; int idxr; char root; bool vis = false; }; Node f1[27],f2[27]; Node tree1[27],tree2[27]; bool judgeSame(Node a,Node b) { bool ok = false; if(a.lchild == b.lchild && a.rchild == b.rchild) { ok
= true; } if(a.lchild == b.rchild && a.rchild == b.lchild) { ok = true; } return ok; } bool judge(char op){ if(op>='0' && op<='9'){ return true; }else{ return false; } } int main() { int n,m; cin>>n; for(int i = 0; i<n; i++) {//存資訊 getchar(); char o1,o2; cin>>f1[i].root>>o1>>o2; if(judge(o1)) f1[i].idxl = o1-'0'; else f1[i].idxl = -1; if(judge(o2)) f1[i].idxr = o2-'0'; else f1[i].idxr = -1; } cin>>m; for(int i = 0; i<m; i++) {//存資訊 char o1,o2; getchar(); cin>>f2[i].root>>o1>>o2; if(judge(o1)) f2[i].idxl = o1-'0'; else f2[i].idxl = -1; if(judge(o2)) f2[i].idxr = o2-'0'; else f2[i].idxr = -1; } for(int i = 0; i<n; i++) {//處理儲存第一棵樹的孩子資訊 int idx = f1[i].root - 'A'; int idl = f1[i].idxl; int idr = f1[i].idxr; if(idl>=0) tree1[idx].lchild = f1[idl].root; else tree1[idx].lchild = '#'; if(idr>=0) tree1[idx].rchild = f1[idr].root; else tree1[idx].rchild = '#'; tree1[idx].vis = true; } // for(int i = 0; i<25; i++){ // if(tree1[i].vis) // cout<<'A'+i<<" "<<tree1[i].lchild<<" "<<tree1[i].rchild<<endl; // } for(int i = 0; i<m; i++) {//處理儲存第二棵樹的孩子資訊 int idx = f2[i].root - 'A'; int idl = f2[i].idxl; int idr = f2[i].idxr; if(idl>=0) tree2[idx].lchild = f2[idl].root; else tree2[idx].lchild = '#'; if(idr>=0) tree2[idx].rchild = f2[idr].root; else tree2[idx].rchild = '#'; tree2[idx].vis = true; } // cout<<endl<<"-----------------------------------------------"<<endl; // for(int i = 0; i<25; i++){ // if(tree2[i].vis) // cout<<" "<<tree2[i].lchild<<" "<<tree2[i].rchild<<endl; // } bool ok = true; for(int i = 0; i<26; i++) {//兩棵樹的相同的節點分別進行比較 if(!judgeSame(tree1[i],tree2[i])) { ok = false; } } if(ok) { cout<<"Yes"<<endl; } else { cout<<"No"<<endl; } return 0; } /* PutIn: 8 A 1 2 B 3 4 C 5 - D - - E 6 - G 7 - F - - H - - 8 G - 4 B 7 6 F - - A 5 1 H - - C 0 - D - - E 2 - PutOut: Yes */ /* PutIn: 8 B 5 7 F - - A 0 3 C 6 - H - - D - - G 4 - E 1 - 8 D 6 - B 5 - E - - H - - C 0 2 G - 3 F - - A 1 4 PutOut: No */
View Code