以下写法是 O(mn2) 还是 O(mn) 的(忽略 map
的复杂度)?似乎是 O(mn) 的?
#include <bits/stdc++.h>
using namespace std;
#define USING_FREAD
namespace Elaina {
#define rep(i, l, r) for (int i = l, i##_end_ = r; i <= i##_end_; ++i)
#define drep(i, l, r) for (int i = l, i##_end_ = r; i >= i##_end_; --i)
#define fi first
#define se second
#define Endl putchar('\n')
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
template<class T> inline T fab(T x) { return x < 0? -x: x; }
template<class T> inline void getmax(T& x, const T& rhs) { x = max(x, rhs); }
template<class T> inline void getmin(T& x, const T& rhs) { x = min(x, rhs); }
#ifdef USING_FREAD
# define CHARRECEI qkgetc()
inline char qkgetc() {
# define BUFFERSIZE 1 << 18
static char BUF[BUFFERSIZE], *p1 = BUF, *p2 = BUF;
return (p1 == p2 && (p2 = (p1 = BUF) + fread(BUF, 1, BUFFERSIZE, stdin), p1 == p2))? EOF : *p1++;
# undef BUFFERSIZE
}
#else
# define CHARRECEI getchar()
#endif
template<class T> inline T readret(T x) {
x = 0; char c; bool f = false;
while (!isdigit(c = CHARRECEI)) if (c == '-') f = true;
for (x = (c ^ 48); isdigit(c = CHARRECEI); x = (x << 1) + (x << 3) + (c ^ 48));
return f? -x: x;
}
template<class T> inline void readin(T& x) {
x = 0; char c; bool f = false;
while (!isdigit(c = CHARRECEI)) if (c == '-') f = true;
for (x = (c ^ 48); isdigit(c = CHARRECEI); x = (x << 1) + (x << 3) + (c ^ 48));
if (f) x = -x;
}
template<class T, class... Args> inline void readin(T& x, Args&... args) {
readin(x), readin(args...);
}
template<class T> inline void writln(T x, char c = '\n') {
static int writ_stk[55], writ_ed;
if (x < 0) putchar('-'), x = -x;
do writ_stk[++writ_ed] = x % 10, x /= 10; while (x);
while (writ_ed) putchar(writ_stk[writ_ed--] ^ 48);
putchar(c);
}
} // namespace Elaina
using namespace Elaina;
const int maxn = 50;
const int inf = 0x3f3f3f3f;
bool sie[1005];
int prime[1005], pcnt;
inline void sieve() {
int n = 1000; sie[1] = true;
for (int i = 2; i <= n; ++i) {
if(!sie[i]) prime[++pcnt] = i;
for (int j = 1; j <= pcnt && i * prime[j] <= n; ++j) {
sie[i * prime[j]] = true;
if (i % prime[j] == 0) break;
}
}
}
vector<int> g[maxn + 5];
inline void add_edge(int u, int v) {
g[u].push_back(v), g[v].push_back(u);
}
int n, m;
inline void input() {
readin(n);
for (int i = 1; i <= n; ++i) g[i].clear();
int fa;
for (int i = 1; i <= n; ++i) {
readin(fa);
if (fa) add_edge(fa, i);
}
}
int siz[maxn + 5], mx[maxn + 5], mn;
void dfs1(int u, int par) {
siz[u] = 0, mx[u] = 0;
for (int v: g[u]) if(v ^ par) {
dfs1(v, u), siz[u] += siz[v];
getmax(mx[u], siz[v]);
}
getmax(mx[u], n - siz[u]);
if(mx[u] < mn) mn = mx[u];
}
ull getHash(int u, int par) {
ull ans = 1, tmp; siz[u] = 1;
for (int v: g[u]) if(v ^ par) {
tmp = getHash(v, u);
ans += tmp * prime[siz[v]];
siz[u] += siz[v];
}
return ans;
}
map< pair<ull, int>, int > table;
signed main() {
sieve();
readin(m);
for (int _ = 1; _ <= m; ++_) {
input();
mn = inf; dfs1(1, 0);
ull h = ULLONG_MAX;
for (int u = 1; u <= n; ++u) if (mx[u] == mn)
getmin(h, getHash(u, 0));
if (!table.count({h, n})) table[{h, n}] = _;
writln(table[{h, n}]);
}
return 0;
}