树的同构
题目背景:
分析:树上hash
hash大法好······听说这个叫套路题,果然我套路不够深······选择GG,就是对于每一个树,分别以每一个点为根求得一个hash值,然后依次比对,然后为了保证结构相同的hash相同,选择每一次hash的时候排一下序就好了,我选择的hash方式就是
p为一个质数表,注意son[cur] 应该要按照hash值由小到大排序,数据很小,直接暴力比较就好。
Source:
/*
created by scarlyw
*/
#include <cstdio>
#include <string>
#include <algorithm>
#include <cstring>
#include <iostream>
#include <cmath>
#include <cctype>
#include <vector>
#include <set>
#include <queue>
#include <ctime>
inline char read() {
static const int IN_LEN = 1024 * 1024;
static char buf[IN_LEN], *s, *t;
if (s == t) {
t = (s = buf) + fread(buf, 1, IN_LEN, stdin);
if (s == t) return -1;
}
return *s++;
}
///*
template<class T>
inline void R(T &x) {
static char c;
static bool iosig;
for (c = read(), iosig = false; !isdigit(c); c = read()) {
if (c == -1) return ;
if (c == '-') iosig = true;
}
for (x = 0; isdigit(c); c = read())
x = ((x << 2) + x << 1) + (c ^ '0');
if (iosig) x = -x;
}
//*/
const int OUT_LEN = 1024 * 1024;
char obuf[OUT_LEN], *oh = obuf;
inline void write_char(char c) {
if (oh == obuf + OUT_LEN) fwrite(obuf, 1, OUT_LEN, stdout), oh = obuf;
*oh++ = c;
}
template<class T>
inline void W(T x) {
static int buf[30], cnt;
if (x == 0) write_char('0');
else {
if (x < 0) write_char('-'), x = -x;
for (cnt = 0; x; x /= 10) buf[++cnt] = x % 10 + 48;
while (cnt) write_char(buf[cnt--]);
}
}
inline void flush() {
fwrite(obuf, 1, oh - obuf, stdout);
}
/*
template<class T>
inline void R(T &x) {
static char c;
static bool iosig;
for (c = getchar(), iosig = false; !isdigit(c); c = getchar())
if (c == '-') iosig = true;
for (x = 0; isdigit(c); c = getchar())
x = ((x << 2) + x << 1) + (c ^ '0');
if (iosig) x = -x;
}
//*/
const int MAXN = 60;
int m, n, x, y;
int chose[MAXN], fa[MAXN], pos[MAXN];
std::vector<int> edge[MAXN];
unsigned int f[MAXN], hash[MAXN][MAXN];
unsigned int p[MAXN] = {0, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107,
109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191,
193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271,
277, 281, 283, 293, 307, 311, 313, 317};
bool vis[MAXN];
bool ans;
inline void add_edge(int x, int y) {
edge[x].push_back(y), edge[y].push_back(x);
}
inline void dfs(int cur, int fa) {
std::vector<unsigned int> st;
for (int p = 0; p < edge[cur].size(); ++p) {
int v = edge[cur][p];
if (v != fa) dfs(v, cur), st.push_back(f[v]);
}
std::sort(st.begin(), st.end());
f[cur] = p[1];
for (int i = 0; i < st.size(); ++i) f[cur] += st[i] * p[i + 1];
}
inline void solve() {
R(m);
for (int i = 1; i <= m; ++i) {
R(n);
for (int j = 1; j <= n; ++j) edge[j].clear();
for (int j = 1; j <= n; ++j) {
R(x);
if (x == 0) continue ;
add_edge(x, j);
}
for (int j = 1; j <= n; ++j) dfs(j, 0), hash[i][j] = f[j];
std::sort(hash[i] + 1, hash[i] + n + 1);
for (int j = 1; j <= i; ++j) {
bool flag = true;
for (int k = 1; k <= n; ++k)
if (hash[j][k] != hash[i][k]) {
flag = false;
break ;
}
if (flag) {
W(j), write_char('\n');
break ;
}
}
}
}
int main() {
solve();
flush();
return 0;
}