此题我的朋友给我上了一课,永远不要惯性思维!
一开始拿到这道题我就是先建树,后面我的朋友带我分析了一波:归根结底就是检查每个节点的左右孩子。所以根本没必要常规建树。
怎么个检查法子呢? 同构的定义是通过交换左右孩子可以使两棵树一样
核心逻辑:两个相同(相同指的是字母一样)节点的两个孩子一样(不区分左右):
(l == l2 && r == r2) || (l == r2 && l2 == r)
后面发现这种思路考虑不到根节点
=> 因为都是检查了相同节点的左右孩子,而根节点不是任何节点的孩子。
除非能够保证两棵树的用到的字母都一样:
for(int i = 0; i < t1.size(); i++) {
char s = get<0>(t1[i]);
bool flag = false;
for(int j = 0; j < t2.size(); j++) {
if(s == get<0>(t2[j])) flag = true;
}
if(!flag) {
cout << "No";
return 0;
}
}
完整代码(包括之前的思路)如下:
// #include <bits/stdc++.h>
// using namespace std;
// struct Tree {
// char symbol;
// char id;
// struct Tree* left;
// struct Tree* right;
// Tree(char s, char i, struct Tree* l, struct Tree* r) : symbol(s), id(i), left(l), right(r) {}
// explicit Tree(char s, char i) : symbol(s), id(i), left(nullptr), right(nullptr) {}
// }
// Tree* buildTree() {
// int n;
// cin >> n;
// vector<tuple<char, char, char>> t;
// vector<int> count(n, 0);
// for(int i = 0; i < n; i++) {
// char s, l, r;
// cin >> s >> l >> r;
// count[l - '0'] += 1;
// count[r - '0'] += 1;
// tuple<char, char, char> temp(s, l, r);
// t.push_back(temp);
// }
// int root = -1;
// for(int i = 0; i < n; i++) {
// if(!count[i]) {
// root = i;
// break;
// }
// }
// root = constructHelper(t, rootid);
// }
// Tree* constructHelper(const vector<tuple<char, char, char>>& t, int rootid) {
// char id_l = get<1>(t[rootid]);
// char id_r = get<2>(t[rootid]);
// Tree* left, right;
// if(id_l == '-') left = nullptr;
// else left = constructHelper(t, id_l - '0');
// if(id_r == '-') right = nullptr;
// else right = constructHelper(t, id_r - '0');
// char s = get<0>(t[rootid]));
// Tree* root = new Tree(s, rootid, left, right);
// return root;
// }
// bool fun(Tree* root1, Tree* root2) {
// if(!root1)
// if(root1->left->symbol != root2->right->symbol) //swap root1 l r
// }
// int main() {
// Tree* root1 = buildTree();
// Tree* root2 = buildTree();
// return 0;
// }
#include <bits/stdc++.h>
using namespace std;
vector<tuple<char, char, char>> buildTree() {
int n;
cin >> n;
vector<tuple<char, char, char>> t;
for(int i = 0; i < n; i++) {
char s, l, r;
cin >> s >> l >> r;
tuple<char, char, char> temp(s, l, r);
t.push_back(temp);
}
return t;
}
int main() {
vector<tuple<char, char, char>> t1 = buildTree();
vector<tuple<char, char, char>> t2 = buildTree();
for(int i = 0; i < t1.size(); i++) {
char s = get<0>(t1[i]);
bool flag = false;
for(int j = 0; j < t2.size(); j++) {
if(s == get<0>(t2[j])) flag = true;
}
if(!flag) {
cout << "No";
return 0;
}
}
for(int i = 0; i < t1.size(); i++) {
char s = get<0>(t1[i]);
char lid = get<1>(t1[i]);
char rid = get<2>(t1[i]);
char l, r;
if(lid == '-') l = '-';
else l = get<0>(t1[lid - '0']);
if(rid == '-') r = '-';
else r = get<0>(t1[rid - '0']);
for(int j = 0; j < t2.size(); j++) {
if(s == get<0>(t2[j])) {
char s2 = get<0>(t2[j]);
char lid2 = get<1>(t2[j]);
char rid2 = get<2>(t2[j]);
char l2, r2;
if(lid2 == '-') l2 = '-';
else l2 = get<0>(t2[lid2 - '0']);
if(rid2 == '-') r2 = '-';
else r2 = get<0>(t2[rid2 - '0']);
if( (l == l2 && r == r2) || (l == r2 && l2 == r) ) {
break;
}else {
cout << "No";
return 0;
}
}
}
}
cout << "Yes";
return 0;
}