Codeforces Round 855 (Div. 3) G. Symmetree AHU树哈希

发布时间 2023-11-03 16:56:25作者: My_opt

(https://codeforces.com/contest/1800/problem/G)

题目如下:

 大意是:给定一颗以1为根节点的树,然后判断这棵树是不是对称的。这里使用AHU算法进行树哈希,在递归的时候对每一个子节点为根的子树求出一个编号,然后在map里面记录。通过判断子树的编号是否一样来判断子树是否同构。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 void solve()
 5 {
 6     int curr_size = 0;
 7     //get_index在这里的作用是对每一种结构的子树做一个离散化,映射成一个数字下标
 8     map<vector<int>, int> get_index;
 9     //存储一种子树结构对应的一个数字下标是否是对称的
10     map<int, bool> is_symmetrical;
11 
12     //dfs函数的目标是求出以node为根节点的子树的编号
13     auto dfs = [&](auto self, int node, int father, vector<vector<int>> &list_node) -> int {
14         vector<int> children;
15         for (auto &child : list_node[node]) {
16             //递归的加入所有子节点编号
17             if (child != father) {
18                 children.emplace_back(self(self, child, node, list_node));
19             }
20         }
21         //排序是为了保证子树结构的唯一性,这样在加入map的时候才不会出错
22         sort(children.begin(), children.end());
23 
24         //如果没有统计过这个编号,那么就统计进去
25         if (!get_index.count(children)) {
26             //判断对称性,出现奇数次的子树不超过1个,并且是对称的,那么就认为这个父节点是对称的
27             //因此,需要统计当前父节点每个子树编号出现的次数
28             map<int, int> count;
29             for (auto &child : children) {
30                 count[child]++;
31             }
32             //oddcnt:奇数子树个数, badcnt:奇数且非对称子树个数
33             int oddcnt = 0, badcnt = 0;
34             for (auto &[child, cnt] : count) {
35                 if (cnt & 1) {
36                     oddcnt++, badcnt += !is_symmetrical[child];
37                 }
38             }
39             //更新结果到map里面
40             is_symmetrical[curr_size] = oddcnt < 2 && !badcnt;
41             get_index[children] = curr_size++;
42         }
43         return get_index[children];
44     };
45 
46     int n;
47     cin >> n;
48     vector<vector<int>> list_node(n);
49     for (int i = 0; i < n - 1; i++) {
50         int u, v;
51         cin >> u >> v;
52         --u, --v;
53         list_node[u].emplace_back(v);
54         list_node[v].emplace_back(u);
55     }
56     cout << (is_symmetrical[dfs(dfs, 0, 0, list_node)] ? "YES" : "NO") << endl;
57 }
58 
59 int main() {
60     int t = 1;
61     cin >> t;
62     while (t--) {
63         solve();
64     }
65     return 0;
66 }