爵士好提

Solution

定义\(u\)控制\(v\)当且仅当\(u\)死后\(v\)也会死

把图建出来,从食物向消费者连边

我们不难想到只能先处理食物,再处理消费者,所以先上个拓扑排序

想一想暴力怎么做,对于每个点我们考虑状压维护这个点受哪些点控制,暴力合并即可。

但显然,这个暴力的复杂度是\(O(n^2)\)的。

考虑到控制的一个性质:若\(x\)控制\(z\)而\(y\)同样控制\(z\),则要么\(x\)控制\(y\),要么\(y\)控制\(x\)

我们不妨考虑根据控制的关系建出一棵树来,\(u\)是\(v\)的祖先当且仅当\(u\)控制\(v\),显然,一个点的答案就是这个点在树上对应点节点为根的子树大小\(-1\)

怎么建出这棵树?

接下来的问题就很显然了,我们考虑每遍历到一条边\((u,v)\)都用\(u\)去更新\(v\)的父亲,具体过程用\(\text{LCA}\)算法即可,我使用倍增实现,需要在线维护倍增数组

Code

#include <cstdio>
#include <iostream>
using namespace std;
inline int read() {
int res = 0, flag = 0; char ch = getchar();
for(; !isdigit(ch); ch = getchar()) if(ch == '-') flag = 1;
for(; isdigit(ch); ch = getchar()) res = (res << 1) + (res << 3) + (ch ^ 48);
if(flag) res = ~res + 1; return res;
}
const int N = 70000;
int n, tail, head, que[N];
int la[N], la1[N], tot, tot1, d[N], fa[N][20], dep[N], sz[N];
struct Edge {int to, nxt;} e[2000010], e1[100000];
inline void build(int u, int v) {e[++tot] = (Edge) {v, la[u]}, la[u] = tot, ++d[v];}
inline void build1(int u, int v) {e1[++tot1] = (Edge) {v, la1[u]}, la1[u] = tot1;}
void update(int x) {
if(x == n + 1) return ;
build1(fa[x][0], x), dep[x] = dep[fa[x][0]] + 1;
for(int i = 1; i <= 17; ++i)
fa[x][i] = fa[fa[x][i - 1]][i - 1];
return ;
}
inline int getlca(int x, int y) {
if(dep[x] < dep[y]) swap(x, y);
for(int i = 17; i + 1; --i)
if(dep[fa[x][i]] >= dep[y]) x = fa[x][i];
if(x == y) return x;
for(int i = 17; i + 1; --i)
if(fa[x][i] != fa[y][i]) x = fa[x][i], y = fa[y][i];
return fa[x][0];
}
void work(int x, int y) {fa[x][0] = (fa[x][0] ? getlca(fa[x][0], y) : y);}
void dfs(int k) {
sz[k] = 1;
for(int v, i = la1[k]; i; i = e1[i].nxt) {
v = e1[i].to;
dfs(v), sz[k] += sz[v];
}
return ;
}
void solve() {
que[tail = 1] = n + 1, dep[n + 1] = 1;
while(++head <= tail) {
update(que[head]);
for(int v, i = la[que[head]]; i; i = e[i].nxt) {
v = e[i].to;
--d[v], work(v, que[head]);
if(!d[v]) que[++tail] = v;
}
}
dfs(n + 1);
}
int main() {
n = read();
for(int v, u = 1; u <= n; ++u) {
v = read();
while(v) build(v, u), v = read();
}
for(int i = 1; i <= n; ++i) if(!d[i]) build(n + 1, i);
solve();
for(int i = 1; i <= n; ++i) printf("%d\n",sz[i] - 1);
}

[ZJOI2012] 灾难 题解的更多相关文章

  1. 【BZOJ2815】[ZJOI2012]灾难 拓扑排序+LCA

    [BZOJ2815][ZJOI2012]灾难 题目描述 阿米巴是小强的好朋友. 阿米巴和小强在草原上捉蚂蚱.小强突然想,果蚂蚱被他们捉灭绝了,那么吃蚂蚱的小鸟就会饿死,而捕食小鸟的猛禽也会跟着灭绝,从 ...

  2. [洛谷P2597] [ZJOI2012]灾难

    洛谷题目链接:[ZJOI2012]灾难 题目描述 阿米巴是小强的好朋友. 阿米巴和小强在草原上捉蚂蚱.小强突然想,如果蚂蚱被他们捉灭绝了,那么吃蚂蚱的小鸟就会饿死,而捕食小鸟的猛禽也会跟着灭绝,从而引 ...

  3. Luogu_2597_[ZJOI2012]灾难 倍增lca + 构造

    Luogu_2597_[ZJOI2012]灾难 倍增lca + 构造 题意: 我们用一种叫做食物网的有向图来描述生物之间的关系:一个食物网有N个点,代表N种生物,如果生物x可以吃生物y,那么从y向x连 ...

  4. 1321. [ZJOI2012] 灾难

    1321. [ZJOI2012] 灾难 ★★☆   输入文件:catas.in   输出文件:catas.out   简单对比时间限制:1 s   内存限制:128 MB [问题描述] 阿米巴是小强的 ...

  5. 洛谷 P2597 [ZJOI2012]灾难 解题报告

    P2597 [ZJOI2012]灾难 题目描述 阿米巴是小强的好朋友. 阿米巴和小强在草原上捉蚂蚱.小强突然想,如果蚂蚱被他们捉灭绝了,那么吃蚂蚱的小鸟就会饿死,而捕食小鸟的猛禽也会跟着灭绝,从而引发 ...

  6. P2597 [ZJOI2012]灾难——拓扑,倍增,LCA

    最近想学支配树,但是基础还是要打好了的: P2597 [ZJOI2012]灾难 这道题是根据食物链链接出一个有向图的关系,求一个物种的灭绝会连带几种物种的灭绝: 求得就是一个点能支配几个点: 如果一个 ...

  7. 【题解】 [ZJOI2012]灾难 (拓扑排序+LCA)

    懒得复制,戳我戳我 Solution: 这题思路很神奇,首先你要知道这个毁灭树是怎么保证实现的:一句话就是如果该节点要被破坏,他的所有父节点就要被破坏,也就只要所有父节点的LCA被破坏就可以,所以我们 ...

  8. 【bzoj2815】[ZJOI2012]灾难 拓扑排序+倍增LCA

    题目描述(转自洛谷) 阿米巴是小强的好朋友. 阿米巴和小强在草原上捉蚂蚱.小强突然想,果蚂蚱被他们捉灭绝了,那么吃蚂蚱的小鸟就会饿死,而捕食小鸟的猛禽也会跟着灭绝,从而引发一系列的生态灾难. 学过生物 ...

  9. P2597 [ZJOI2012]灾难

    \(\color{#0066ff}{ 题目描述 }\) 阿米巴是小强的好朋友. 阿米巴和小强在草原上捉蚂蚱.小强突然想,如果蚂蚱被他们捉灭绝了,那么吃蚂蚱的小鸟就会饿死,而捕食小鸟的猛禽也会跟着灭绝, ...

随机推荐

  1. && 和 ||粗解

    可以这么理解 &&是来找假的,如果找到假就返回假,如果找不到,就返回最后一个真 ||是来找真的,如果找到真就返回真,如果找不到,就返回最后一个假 var speed = 12; var ...

  2. STC8H开发(十六): GPIO驱动XL2400无线模块

    目录 STC8H开发(一): 在Keil5中配置和使用FwLib_STC8封装库(图文详解) STC8H开发(二): 在Linux VSCode中配置和使用FwLib_STC8封装库(图文详解) ST ...

  3. mybatisplus-sql注入器

    sql注入器 使用mybatisplus只需要继承BaseMapper接口即可使用:但是有新的需求需要扩展BaseMapper里面的功能时可使用sql注入器. 扩展BaseMapper里面的功能 点击 ...

  4. vsftpd 操作手册 - 完整版

    vsftpd # 目录 - ftp 简介 - vsftpd 简介 - vsftpd 安装&卸载 - vsftpd 配置文件 - vsftpd 认证模板 - vsftpd 配置模板 # 目录详解 ...

  5. DIN 66025标准下G Code基础代码释义

    基础/前提 XYZ指示常规的三个轴号,PQUVW为可以增加的五个轴,ABC为可以增加的旋转轴 实例 G0 快速定位(点位运动) G1 直线运动(插补) G2 顺时针圆弧运动(插补) G3 逆时针圆弧运 ...

  6. DataGridView控件绑定数据之后,置顶操作

    一个小小的置顶,就搞了半个小时,还是记录一下吧. 1.第一个问题就是datatable的插入只能是Insert DataRow,但是获取选中的行,都是DataGridViewRow,不能直接转换. 找 ...

  7. Html飞机大战(四):状态的切换(界面加载类的编辑)

    好家伙,接着写   既然我们涉及到状态了,那么我们也会涉及到状态的切换   那么我们怎样切换状态呢? 想象一下,如果我玩的游戏暂停了,那么我们肯定是通过点击或者按下某个按键来让游戏继续   这里我们选 ...

  8. 移动教室APP

    软件名:VERIMAG 官网链接:http://www.verimag.ru/mobilnoe-obrazovanie.html 移动课堂,充满活力的气息.走在时代前沿的同时,也对教育者对于编制课件的 ...

  9. nginx的安装和配置

    目录 目录 一.购买下载SSL证书 二.修改Nginx配置信息 三.重启Nginx 一.购买下载SSL证书 SSL证书阿里云做活动期间可以免费申请,购买SSL证书时选择单域名-DV SSL-免费版即可 ...

  10. Arrays.asList()你真的知道怎么用吗?

    发现问题 前几天在看别人的项目的时候,发现一个问题,简单复现一下这个问题 // 注意这是一个Integer对象的数组哦 Integer[] arr = new Integer[]{9999,88,77 ...