题目链接 HDU-6647
有一棵N个点构成的无根树,我们可以任选一点开始进行dfs跑,得到一个括号序,现在我们想知道跑完整个dfs,有多少种括号序?
于是,可以比较容易的想到,我们可以推一个dp方程来解出从一个点出发,得到的方案数,假设表示以u为子树的根节点时候的跑完下面子树的种类数,那么可以看到,其中,表示u的不同形态的子树的个数。
于是,我们可以根据这个式子来进行DP得到目前假设的根节点的值,然后再根据该式子可以进行换根DP得到剩下以每个点为根时候的答案值,当然,当以它为根时候的树跟其他点为根的树是同构的时候,这时只需要算一个的答案就可以了。
然后,这里的哈希值,我选用了随机数,因为一开始被卡了。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <bitset>
#include <unordered_map>
#include <unordered_set>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
#define pii pair<int, int>
#define MP(a, b) make_pair(a, b)
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
vector<int> Prime;
bool not_Prime[1300007] = {false};
void Prime_Init()
{
for(int i=2; Prime.size() <= 100000 && i<1300000; i++)
{
if(!not_Prime[i])
{
Prime.push_back(i);
for(int j = i * 2; j < 1300000; j += i) not_Prime[j] = true;
}
}
}
const ll mod = 998244353;
const int maxN = 1e5 + 7;
inline void MOD(ll &x) { x = x >= mod ? x % mod : x; }
inline ll mul(ll a, ll b) { a *= b; MOD(a); return a; }
inline ll qpow(ll a, ll b = mod - 2)
{
ll ans = 1;
while(b)
{
if(b & 1) ans = mul(ans, a);
b >>= 1;
a = mul(a, a);
}
return ans;
}
ll jc[maxN], inv_jc[maxN];
int N;
namespace Graph
{
int head[maxN], cnt;
struct Eddge
{
int nex, to;
Eddge(int a=-1, int b=0):nex(a), to(b) {}
} edge[maxN << 1];
inline void addEddge(int u, int v)
{
edge[cnt] = Eddge(head[u], v);
head[u] = cnt++;
}
inline void _add(int u, int v) { addEddge(u, v); addEddge(v, u); }
inline void init()
{
cnt = 0;
for(int i=1; i<=N; i++) head[i] = -1;
}
};
using namespace Graph;
unordered_map<ull, int> mp[maxN];
unordered_map<ull, int>::iterator it;
unordered_map<ull, bool> root_Tree;
uit siz[maxN], du[maxN];
ll dp[maxN], ans;
ull f[maxN];
void dfs(int u, int fa)
{
siz[u] = 1;
f[u] = 1;
int num = 0;
ll pi_dp_v = 1;
for(int i=head[u], v; ~i; i=edge[i].nex)
{
v = edge[i].to;
if(v == fa) continue;
dfs(v, u);
num++;
f[u] += f[v] * Prime[siz[v]];
siz[u] += siz[v];
mp[u][f[v]]++;
pi_dp_v = mul(pi_dp_v, dp[v]);
}
du[u] = num;
dp[u] = mul(jc[num], pi_dp_v);
for(it = mp[u].begin(); it != mp[u].end(); it++)
{
dp[u] = mul(dp[u], inv_jc[it->second]);
}
}
void ex_dfs(int u, int fa, ull fa_f, ll fa_dp)
{
ull now_f = f[u] + fa_f * Prime[N - siz[u]];
ll now_dp = dp[u];
now_dp = mul(now_dp, fa_dp);
now_dp = mul(now_dp, mul(inv_jc[du[u]], jc[du[u] + 1]));
now_dp = mul(now_dp, mul(jc[mp[u][fa_f]], inv_jc[mp[u][fa_f] + 1]));
mp[u][fa_f]++;
du[u]++;
if(!root_Tree[now_f])
{
root_Tree[now_f] = true;
ans += now_dp;
MOD(ans);
}
ull nex_f; ll nex_dp;
for(int i=head[u], v; ~i; i=edge[i].nex)
{
v = edge[i].to;
if(v == fa) continue;
nex_f = now_f - f[v] * Prime[siz[v]];
nex_dp = mul(now_dp, qpow(dp[v]));
nex_dp = mul(nex_dp, mul(inv_jc[du[u]], jc[du[u] - 1]));
nex_dp = mul(nex_dp, mul(jc[mp[u][f[v]]], inv_jc[mp[u][f[v]] - 1]));
ex_dfs(v, u, nex_f, nex_dp);
}
}
inline void pre_Do()
{
Prime_Init();
for(int i=1, l, r; i<=100000; i++)
{
l = rand() % 100000 + 1; r = rand() % 100000 + 1;
swap(Prime[l], Prime[r]);
}
jc[0] = 1;
for(ll i = 1; i < maxN; i++) jc[i] = mul(i, jc[i - 1]);
inv_jc[maxN - 1] = qpow(jc[maxN - 1]);
for(int i = maxN - 2; i >= 0; i--) inv_jc[i] = mul(inv_jc[i + 1], i + 1);
}
int main()
{
pre_Do();
int T; scanf("%d", &T);
while(T--)
{
scanf("%d", &N);
root_Tree.clear();
for(int i=1; i<=N; i++) mp[i].clear();
init();
for(int i=1, u, v; i<N; i++)
{
scanf("%d%d", &u, &v);
_add(u, v);
}
dfs(1, 0);
ans = dp[1];
root_Tree[f[1]] = true;
ll nex_dp = 0; ull nex_f = 0;
for(int i=head[1], u; ~i; i=edge[i].nex)
{
u = edge[i].to;
nex_f = f[1] - f[u] * Prime[siz[u]];
nex_dp = mul(dp[1], qpow(dp[u]));
nex_dp = mul(mul(nex_dp, inv_jc[du[1]]), jc[du[1] - 1]);
nex_dp = mul(nex_dp, mul(jc[mp[1][f[u]]], inv_jc[mp[1][f[u]] - 1]));
ex_dfs(u, 1, nex_f, nex_dp);
}
printf("%lld\n", ans);
}
return 0;
}