rt,怀疑是本机和评测机运行时有区别,就第一个点来说,本机运行 0.03s,评测直接 TLE ...懵逼...
先说一下我的思路:在拓扑排序时,对于每一个节点 x:
然后在答案树上累加答案就行了。复杂度应该是 O(MlgN)
然而全TLE了qwq,求教 dalao...
代码:(fst1 是原有向图,fst2 是答案树,倍增树只用存倍增数组就行了)
#include <ctime>
#include <cstdio>
#include <iostream>
using namespace std;
const int inf = 2147483647;
const int MAXN = 100005;
struct edge {
int v, pre;
} e[MAXN<<2];
int N, fst1[MAXN], fst2[MAXN], tote;
int vis[MAXN];
int lg[MAXN], dep[MAXN], fa[MAXN][35];
int ans[MAXN];
inline int read()
{
register int o = 0, oo = 0;
register char c = getchar();
while (c < '0' || c > '9') oo |= (c == '-'), c = getchar();
while (c >='0' && c <='9') o = (o<<3)+(o<<1)+(c&15), c = getchar();
return oo ? -o : o;
}
void adde1(int a, int b, int k) { e[k] = (edge){b, fst1[a]}, fst1[a] = k;}
void adde2(int a, int b, int k) { e[k] = (edge){b, fst2[a]}, fst2[a] = k;}
int lca(int a, int b)
{
if (dep[a] < dep[b]) a ^= b ^= a ^= b;
while (dep[a] > dep[b]) a = fa[a][lg[dep[a]-dep[b]]];
if (a == b) return a;
for (int i=lg[dep[a]]; i>=0; i--)
if (fa[a][i] != fa[b][i]) a = fa[a][i], b = fa[b][i];
return fa[a][0];
}
int toposort(int x) // while building the tree
{
vis[x] = 1;
for (int o=fst1[x]; o; o=e[o].pre)
if (!vis[e[o].v]) toposort(e[o].v);
if (fst1[x]) {
int mind = inf, f;
for (int o=fst1[x]; o; o=e[o].pre)
if (dep[e[o].v] < mind)
mind = dep[e[o].v], f = e[o].v;
fa[x][0] = f, dep[x] = dep[f] + 1;
for (int i=1; i<=lg[dep[x]]; i++)
fa[x][i] = fa[fa[x][i-1]][i-1];
int anc = x;
for (int o=fst1[x]; o; o=e[o].pre)
anc = lca(anc, e[o].v);
adde2(anc, x, ++tote);
}
}
void init()
{
N = read();
for (int i=1; i<=N; i++) {
int j = read();
if (!j) adde1(i, 0, ++tote);
for (; j;) {
adde1(i, j, ++tote);
j = read();
}
}
}
int solve(int x)
{
for (int o=fst2[x]; o; o=e[o].pre) ans[x] += solve(e[o].v) + 1;
return ans[x];
}
void work()
{
for (int i=1; i<=N; i++) lg[i] = lg[i-1] + ((1<<(lg[i-1]+1)) == i);
for (int i=1; i<=N; i++) if (!vis[i]) toposort(i);
solve(0);
for (int i=1; i<=N; i++) printf("%d\n", ans[i]);
// printf("Time used = %.2f\n", (double)clock() / CLOCKS_PER_SEC);
}
int main()
{
// freopen("P2597_1.in", "r", stdin);
// freopen("output.out", "w", stdout);
init();
work();
}