判断无根树是否同构,时间复杂度Θ(∑n)。
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
| #include <bits/stdc++.h> using namespace std; using ll = long long; using ull = unsigned long long;
mt19937_64 rng{ chrono::steady_clock::now().time_since_epoch().count() }; const int N = 3e5 + 8; ull hsh[N];
int main() { for (int i = 0; i < N; i++) { hsh[i] = rng(); }
int m; cin >> m;
map<ull, int> mp; for (int id = 1; id <= m; i++d) { int n; cin >> n;
vector<vector<int>> E(n); for (int u = 0; u < n; ++u) { int v; cin >> v; if (v) v--, E[u].push_back(v), E[v].push_back(u); }
vector<int> ctr, siz(n), mss(n), dep(n); auto getctr = [&](this auto&& dfs, int u, int p) -> void { siz[u] = 1, mss[u] = 0; for (auto v : E[u]) { if (v == p) continue; dfs(v, u); siz[u] += siz[v]; mss[u] = max(mss[u], siz[v]); } mss[u] = max(mss[u], n - siz[u]); if (mss[u] <= n / 2) ctr.push_back(u); };
getctr(0, -1); if (ctr.size() == 1) { ctr.push_back(ctr[0]); }
array<ull, 2> res; auto dfs = [&](this auto&& dfs, int u, int p) -> ull { siz[u] = 1; ull res = dep[u] * hsh[0]; for (auto& v : E[u]) { if (v == p) continue; dep[v] = dep[u] + 1; res += dfs(v, u) * hsh[siz[v]]; siz[u] += siz[v]; } return res; }; for (int i = 0; i < 2; i++) { dep[ctr[i]] = 1; res[i] = dfs(ctr[i], -1); } sort(res.begin(), res.end());
ull tmp = res[0] * hsh[0] + res[1]; if (!mp.count(tmp)) mp[tmp] = id; cout << mp[tmp] << "\n"; }
return 0; }
|