連結:https://tioj.ck.tp.edu.tw/problems/1214
題目大意
判斷兩棵樹是否同構
題解
如果兩棵樹是一樣的,那可以先將樹上唯二的重心、或直徑中點找出來,那就可以一個相同的點,然後再比對樹的最小括號表示法即可完成題目要求。
AC Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
| #include<bits/stdc++.h> using namespace std;
vector<int> V[100];
int far,far2; int dist=0; void dfs(int v, int fa, int d) { if( d > dist ){ far=v; dist=d; } for(int e:V[v]) { if(e==fa)continue; dfs(e,v,d+1); } }
vector<int> path; bool findpath(int v, int fa) { path.push_back(v); if( v == far2 ) return true; for(int e:V[v]) { if( e==fa ) continue; if( findpath(e,v) ) return true; } path.pop_back(); return false; } vector<int> findMid() { vector<int> ans; far=1; dist=0; dfs(1,1,0); dist=0; far2=far; dfs(far,far,0); path.clear(); findpath(far,far); int sz = path.size(); ans.push_back(path[sz/2]); if( sz%2 == 0 ) ans.push_back(path[sz/2-1]); return ans; }
string hash(int v,int fa) { vector<string> res; for(int e:V[v]) { if(e==fa)continue; res.push_back( ::hash(e,v) ); } sort(res.begin(),res.end()); string h="("; for(auto &s:res) h+=s; h+=")"; return h; }
int main() { ios::sync_with_stdio(false); cin.tie(0);
int s,e,N; while(cin>>N,N) { vector<string> h[2]; for(int _=0;_<2;_++) { for(int i=1;i<=N;++i) V[i].clear(); for(int i=1;i<N;++i) { cin>>s>>e; V[s].push_back(e); V[e].push_back(s); } auto mids = findMid(); for(int v:mids) h[_].push_back(::hash(v,v)); sort(h[_].begin(),h[_].end()); } if( h[0]==h[1] )cout<<"Same\n"; else cout<<"Different\n"; } }
|