diff --git a/TangDou/Topic/HuanGenDp/SubTree.cpp b/TangDou/Topic/HuanGenDp/SubTree.cpp index a944fda..8c87eef 100644 --- a/TangDou/Topic/HuanGenDp/SubTree.cpp +++ b/TangDou/Topic/HuanGenDp/SubTree.cpp @@ -1,53 +1,66 @@ #include using namespace std; -const int N = 100010; +const int N = 100010, M = N << 1; #define int long long #define endl "\n" -int dp1[N], dp2[N], mod; -int pro1[N], pro2[N]; -vector edge[N]; + +// 链式前向星 +int e[M], h[N], idx, w[M], ne[M]; +void add(int a, int b, int c = 0) { + e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx++; +} + +int f[N], g[N], mod; +int pre[N], suff[N]; void dfs1(int u, int fa) { - dp1[u] = 1; - vector edgeson; - for (int i = 0; i < edge[u].size(); i++) { - int v = edge[u][i]; + f[u] = 1; + vector son; + for (int i = h[u]; ~i; i = ne[i]) { + int v = e[i]; if (v == fa) continue; dfs1(v, u); - dp1[u] = dp1[u] * (dp1[v] + 1) % mod; - edgeson.push_back(v); // 将子节点加入集合,方便之后操作 + f[u] = f[u] * (f[v] + 1) % mod; + son.push_back(v); // 将子节点加入集合,方便之后操作 } int pre1 = 1; int pre2 = 1; - for (int i = 0; i < edgeson.size(); i++) { - pro1[edgeson[i]] = pre1; - pre1 = pre1 * (dp1[edgeson[i]] + 1) % mod; - } // 预处理前缀积 - for (int i = edgeson.size() - 1; i >= 0; i--) { - pro2[edgeson[i]] = pre2; - pre2 = pre2 * (dp1[edgeson[i]] + 1) % mod; - } // 预处理后缀积 + + // 预处理前缀积 + for (int i = 0; i < son.size(); i++) { + pre[son[i]] = pre1; + pre1 = pre1 * (f[son[i]] + 1) % mod; + } + + // 预处理后缀积 + for (int i = son.size() - 1; i >= 0; i--) { + suff[son[i]] = pre2; + pre2 = pre2 * (f[son[i]] + 1) % mod; + } } + void dfs2(int u, int fa) { - if (fa == -1) - dp2[u] = 1; // 特判根节点 - else - dp2[u] = (dp2[fa] * (pro1[u] * pro2[u] % mod) % mod + 1) % mod; - for (int i = 0; i < edge[u].size(); i++) { - if (edge[u][i] == fa) continue; - dfs2(edge[u][i], u); + g[u] = (g[fa] * (pre[u] * suff[u] % mod) % mod + 1) % mod; + for (int i = h[u]; ~i; i = ne[i]) { + int v = e[i]; + if (v == fa) continue; + dfs2(v, u); } } + signed main() { + // 初始化链式前向星 + memset(h, -1, sizeof h); + int n; cin >> n >> mod; for (int i = 1; i < n; i++) { int a, b; cin >> a >> b; - edge[a].push_back(b); - edge[b].push_back(a); + add(a, b), add(b, a); } dfs1(1, -1); + g[1] = 1; dfs2(1, -1); - for (int i = 1; i <= n; i++) cout << dp1[i] * dp2[i] % mod << endl; + for (int i = 1; i <= n; i++) cout << f[i] * g[i] % mod << endl; } \ No newline at end of file