快被灭绝树灭绝了。
Pre
气死了,\(dnc\)数组初始为0就会是错的,初始为\(-1\)就是对的。
好像存在更新之后\(dnc[i]\)为0的情况。
求大佬教我为什么会有这种情况!!!
调了一个小时。
不过灭绝树还是可以。
Solution
对每一个点的儿子找他们重建树中的\(LCA\),在重建树中统计就是了。
Code
#include <bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define xx first
#define yy second
using namespace std;
const int N = 500000 + 5;
int cd[N];
int n;
int top[N], rd[N], dnc[N];
queue<int> Q;
struct GR {
int fr[N], to[N], h[N], tot, sz[N], fa[N][22], dep[N], deb;
inline void add (int u, int v) {
if (!deb) {
swap (u, v);
cd[v]++;
}
tot++;
fr[tot] = h[u];
to[tot] = v;
h[u] = tot;
}
inline void update (int u, int v) {
dep[u] = dep[v] + 1;
fa[u][0] = v;
for (int i = 1; i <= 19; ++i) {
fa[u][i] = fa[fa[u][i - 1]][i - 1];
}
}
inline int LCA (int u, int v) {
if (dep[u] < dep[v]) {
swap (u, v);
}
while (dep[u] != dep[v]) {
for (int i = 19; i >= 0; --i) {
if (dep[fa[u][i]] >= dep[v]) {
u = fa[u][i];
}
}
}
while (u != v) {
for (int i = 19; i >= 0; --i) {
if (fa[u][i] != fa[v][i]) {
u = fa[u][i];
v = fa[v][i];
}
}
if (fa[u][0] == fa[v][0]) {
u = fa[u][0];
v = fa[v][0];
break;
}
}
return u;
}
inline void dfs () {
while (Q.size ()) {
Q.pop ();
}
for (int i = 1; i <= n; ++i) {
if (!cd[i]) {
Q.push (i);
}
}
while (Q.size ()) {
int tmp = Q.front ();
if (tmp != n + 1) {
sz[tmp] += 1;
}
Q.pop ();
for (int i = h[tmp]; i; i = fr[i]) {
int v = to[i];
sz[v] += sz[tmp];
/*if (v == 2330) {
printf ("%d %d %d %d\n", v, tmp, sz[v], sz[tmp]);
}*/
cd[v]--;
if (!cd[v]) {
Q.push (v);
}
}
}
}
}x, y;
inline void Top ();
int main () {
freopen ("testdata.in", "r", stdin);
freopen ("testdata.out", "w", stdout);
memset (dnc, -1, sizeof (dnc));
x.deb = 1;
scanf ("%d", &n);
for (int i = 1; i <= n; ++i) {
int tmp;
while (1) {
scanf ("%d", &tmp);
if (!tmp) {
break;
}
x.add (tmp, i);
rd[i]++;
}
}
Top();
y.dfs ();
for (int i = 1; i <= n; ++i) {
printf ("%d\n", y.sz[i] - 1);
}
return 0;
}
inline void Top () {
for (int i = 1; i <= n; ++i) {
if (!rd[i]) {
x.add (n + 1, i);
rd[i]++;
}
}
while (Q.size ()) {
Q.pop ();
}
Q.push (n + 1);
while (Q.size ()) {
int tmp = Q.front();
Q.pop();
if (tmp != n + 1) {
y.add (dnc[tmp], tmp);
y.update (tmp, dnc[tmp]);
}
for (int i = x.h[tmp]; i; i = x.fr[i]) {
int v = x.to[i];
rd[v]--;
if (!rd[v]) {
Q.push(v);
}
if (dnc[v] < 0) {
dnc[v] = tmp;
}
else {
dnc[v] = y.LCA (dnc[v], tmp);
}
}
}
}
Conclusion
这时重建一次树,总觉得会有重建\(n\)次树的题目,但是我没遇到过。
另外,论初始化的重要性。