您的位置:首页 > 其它

BZOJ 2815: [ZJOI2012]灾难

2017-01-05 21:35 344 查看
呃,题面没了,大概就是给出一些生物之间的捕食关系,求灭绝树每个点的灾难值。

拓扑排序之后倒着加入点,动态维护fa[][]数组,倍增法求LCA,当然大佬愿意写动态树也是极好的……

#include <cstdio>

inline int nextChar(void) {
const int siz = 1024;

static char buf[siz];
static char *hd = buf + siz;
static char *tl = buf + siz;

if (hd == tl)
fread(hd = buf, 1, siz, stdin);

return *hd++;
}

inline int nextInt(void) {
register int ret = 0;
register int neg = false;
register int bit = nextChar();

for (; bit < 48; bit = nextChar())
if (bit == '-')neg ^= true;

for (; bit > 47; bit = nextChar())
ret = ret * 10 + bit - 48;

return neg ? -ret : ret;
}

const int siz = 800005;

int n;

int cnt[siz];

int tot1;
int hd1[siz];
int to1[siz];
int nt1[siz];

inline void add1(int u, int v)
{
nt1[tot1] = hd1[u]; to1[tot1] = v; hd1[u] = tot1++;
}

int tot2;
int hd2[siz];
int to2[siz];
int nt2[siz];

inline void add2(int u, int v)
{
nt2[tot2] = hd2[u]; to2[tot2] = v; hd2[u] = tot2++;
}

int dep[siz], fa[siz][25];

inline int lca(int a, int b)
{
if (a == -1)
return b;

if (dep[a] < dep[b])
a ^= b ^= a ^= b;

for (int i = 24; i >= 0; --i)
if (dep[fa[a][i]] >= dep[b])
a = fa[a][i];

if (a == b)
return a;

for (int i = 24; i >= 0; --i)
if (fa[a][i] != fa[b][i])
a = fa[a][i],
b = fa[b][i];

return fa[a][0];
}

int que[siz], head, tail;

int sz[siz];

void dfs(int u)
{
for (int i = hd2[u]; ~i; i = nt2[i])
dfs(to2[i]), sz[u] += sz[to2[i]];

++sz[u];
}

signed main(void)
{
n = nextInt();

for (int i = 0; i <= n; ++i)
hd1[i] = hd2[i] = -1;

for (int i = 1, t; i <= n; ++i)
while (t = nextInt(), t)
add1(i, t), ++cnt[t];

for (int i = 1; i <= n; ++i)
if (!cnt[i])que[tail++] = i;

while (head != tail)
{
int u = que[head++], v;

for (int i = hd1[u]; ~i; i = nt1[i])
if (!(--cnt[v = to1[i]]))que[tail++] = v;
}

for (int i = tail - 1; i >= 0; --i)
{
int u = que[i], v = -1;

for (int j = hd1[u]; ~j; j = nt1[j])
v = lca(v, to1[j]);

if (v == -1)v = 0;

add2(v, u);

fa[u][0] = v;

dep[u] = dep[v] + 1;

for (int j = 1; j < 25; ++j)
fa[u][j] = fa[fa[u][j - 1]][j - 1];
}

dfs(0);

for (int i = 1; i <= n; ++i)
printf("%d\n", sz[i] - 1);
}


@Author: YouSiki
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: