【题意】

求把每个点删除后,不可达点的数目。

【思路】

构造一棵“灭绝树”,要求这棵树满足如果删除根节点后则该子树内的所有结点都不可达。则答案为子树大小-1。

如何构造这棵“灭绝树”?

将原图拓扑排序。当我们处理u的时候保证对u的所有食物已经建好树。引入0号节点,以之为所有生产者的食物。设u的食物为v[0..k],当我们至少把v[0..k]的LCA删掉之后u会灭绝,因此由LCA向u连边。增量构造LCA所需信息dep,fa。

 鉴于写dfs的时候发生了一些奇奇怪怪的事(包括卡了下bzoj的评测机 lol,就把dfs改成了bfs

【题解链接】

http://fanhq666.blog.163.com/blog/static/8194342620124274154996/

【代码】

 #include<set>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define trav(u,i,f) for(int i=front[u][f];i;i=e[i][f].nxt)
#define FOR(a,b,c) for(int a=(b);a<=(c);a++)
using namespace std; typedef long long ll;
const int N = 1e5+;
const int M = 2e6+;
const int D = ; ll read() {
char c=getchar();
ll f=,x=;
while(!isdigit(c)) {
if(c=='-') f=-; c=getchar();
}
while(isdigit(c))
x=x*+c-'',c=getchar();
return x*f;
} struct Edge {
int v,nxt;
}e[M][];
int en[]={,},front[N][];
void adde(int u,int v,int f)
{
e[++en[f]][f]=(Edge){v,front[u][f]}; front[u][f]=en[f];
} int n;
int in[N],fa[N][D],dep[N],siz[N];
queue<int> q;
vector<int> tp; void topo()
{
FOR(i,,n) if(!in[i])
q.push(i);
while(!q.empty()) {
int u=q.front(); q.pop();
tp.push_back(u);
trav(u,i,) {
int v=e[i][].v;
if(!(--in[v])) {
q.push(v);
}
}
}
}
int lca(int u,int v)
{
if(u==-) return v;
if(dep[u]<dep[v]) swap(u,v);
int t=dep[u]-dep[v];
FOR(i,,D-)
if(t&(<<i)) u=fa[u][i];
if(u==v) return u;
for(int i=D-;i>=;i--)
if(fa[u][i]!=fa[v][i])
u=fa[u][i],v=fa[v][i];
return fa[u][];
}
void build_tree()
{
for(int i=tp.size()-;i>=;i--) {
int u=tp[i];
int lc=-;
trav(u,i,)
lc=lca(lc,e[i][].v);
lc=lc==-?:lc;
adde(lc,u,);
dep[u]=dep[lc]+;
fa[u][]=lc;
FOR(i,,D-) fa[u][i]=fa[fa[u][i-]][i-];
}
}
int vis[N];
void getans(int u,int fa)
{
tp.clear();
q.push();
while(!q.empty()) {
int u=q.front(); q.pop();
tp.push_back(u);
trav(u,i,) {
int v=e[i][].v;
if(!vis[v])
vis[v]=,q.push(v);
}
}
for(int i=tp.size()-;i>=;i--) {
int u=tp[i];
siz[u]=;
trav(u,i,)
siz[u]+=siz[e[i][].v];
}
}
int main()
{
//freopen("in.in","r",stdin);
//freopen("out.out","w",stdout);
n=read();
int x;
FOR(i,,n) {
while(x=read(),x) {
adde(i,x,); in[x]++;
}
}
topo();
build_tree();
getans(,-);
FOR(i,,n) printf("%d\n",siz[i]-);
return ;
}

bzoj 2815 [ZJOI2012]灾难(构造,树形DP)的更多相关文章

  1. BZOJ 2815: [ZJOI2012]灾难

    呃,题面没了,大概就是给出一些生物之间的捕食关系,求灭绝树每个点的灾难值. 拓扑排序之后倒着加入点,动态维护fa[][]数组,倍增法求LCA,当然大佬愿意写动态树也是极好的…… #include &l ...

  2. BZOJ 2815: [ZJOI2012]灾难 拓扑排序+倍增LCA

    这种问题的转化方式挺巧妙的. Code: #include <bits/stdc++.h> #define N 100000 #define M 1000000 #define setIO ...

  3. [BZOJ 4033] [HAOI2015] T1 【树形DP】

    题目链接:BZOJ - 4033 题目分析 使用树形DP,用 f[i][j] 表示在以 i 为根的子树,有 j 个黑点的最大权值. 这个权值指的是,这个子树内部的点对间距离的贡献,以及 i 和 Fat ...

  4. [BZOJ 4455] [ZJOI 2016] 小星星 (树形dp+容斥原理+状态压缩)

    [BZOJ 4455] [ZJOI 2016] 小星星 (树形dp+容斥原理+状态压缩) 题面 给出一棵树和一个图,点数均为n,问有多少种方法把树的节点标号,使得对于树上的任意两个节点u,v,若树上u ...

  5. BZOJ 2286 消耗战 (虚树+树形DP)

    给出一个n节点的无向树,每条边都有一个边权,给出m个询问,每个询问询问ki个点,问切掉一些边后使得这些顶点无法与顶点1连接.最少的边权和是多少.(n<=250000,sigma(ki)<= ...

  6. AIM Tech Round 3 (Div. 1) (构造,树形dp,费用流,概率dp)

    B. Recover the String 大意: 求构造01字符串使得子序列00,01,10,11的个数恰好为$a_{00},a_{01},a_{10},a_{11}$ 挺简单的构造, 注意到可以通 ...

  7. BZOJ 2435 道路修建 NOI2011 树形DP

    一看到这道题觉得很水,打了递归树形DP后RE了一组,后来发现必须非递归(BFS) 递归版本84分: #include<cstdio> #include<cstring> #in ...

  8. BZOJ 2878: [Noi2012]迷失游乐园( 树形dp )

    一棵树的话直接树形dp(求出往下走和往上走的期望长度). 假如是环套树, 环上的每棵树自己做一遍树形dp, 然后暴力枚举(环上的点<=20)环上每个点跑经过环上的路径就OK了. -------- ...

  9. BZOJ 2314: 士兵的放置( 树形dp )

    树形dp... dp(x, 0)表示结点x不放士兵, 由父亲控制: dp(x, 1)表示结点x不放士兵, 由儿子控制: dp(x, 2)表示结点x放士兵. ---------------------- ...

随机推荐

  1. 4.3 spring-嵌入式beans标签的解析

    对于嵌入式的beans标签,想信大家很少使用过,或者接触过,起码,我本人就没用过. 它非常类似于Import标签所提供的功能; 使用如下: <?xml version="1.0&quo ...

  2. java.lang.NoSuchMethodError: javaxservlet.http.HttpServletRequest.isAsyncStarted()Z

    鸣谢网址:http://stackoverflow.com/questions/25940571/java-lang-nosuchmethoderror-javaxservlet-http-https ...

  3. Ubuntu的挂起和休眠

    Ubuntu的挂起和休眠 之前一直没关注过这方面的信息,因为以前只是在台式机上面用Ubuntu,笔记本一直都是Windows.随着Windows越来越傻冒,最近决定将常用系统转为Ubuntu,才注意到 ...

  4. js 计时器

    <html><head><script type="text/javascript">var count=0;var t ;function t ...

  5. 时序列数据库武斗大会之 TSDB 名录 Part 1

    [编者按] 刘斌,OneAPM后端研发工程师,拥有10多年编程经验,参与过大型金融.通信以及Android手机操作系的开发,熟悉Linux及后台开发技术.曾参与翻译过<第一本Docker书> ...

  6. 正确使用STL-MAP中Erase函数

    一切尽在代码中. #include <iostream> #include <map> #include <string> using namespace std ...

  7. 云风的BLOG❳可靠 UDP 传输

    http://mp.weixin.qq.com/s?__biz=MzA3NjYxOTA0MQ==&mid=405432715&idx=1&sn=2e40ceafd4b298e1 ...

  8. http://www.linuxidc.com/Linux/2007-09/7399.htm

    http://www.linuxidc.com/Linux/2007-09/7399.htm

  9. 李洪强iOS开发之使用CycleScrollView实现轮播图

    01 导入头文件,并且定义CycleScrollView属性 02 初始化,设置frame并且添加到collectionView上 03 调用方法并且设置轮播的图片

  10. Java经典书籍

    Java Web开发教程---孙霞JSP应用开发详解(第三版)---刘晓华.张健.周慧贞Spring in Action---Craig Walls精通Struts基于MVC的Java Web设计与开 ...