树的同构 -

此题我的朋友给我上了一课,永远不要惯性思维!

一开始拿到这道题我就是先建树,后面我的朋友带我分析了一波:归根结底就是检查每个节点的左右孩子。所以根本没必要常规建树。

怎么个检查法子呢? 同构的定义是通过交换左右孩子可以使两棵树一样 

核心逻辑:两个相同(相同指的是字母一样)节点的两个孩子一样(不区分左右):

(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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值