【题意】

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

【思路】

构造一棵“灭绝树”,要求这棵树满足如果删除根节点后则该子树内的所有结点都不可达。则答案为子树大小-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. 1061: [Noi2008]志愿者招募 - BZOJ

    Description 申奥成功后,布布经过不懈努力,终于成为奥组委下属公司人力资源部门的主管.布布刚上任就遇到了一个难题:为即将启动的奥运新项目招募一批短期志愿者.经过估算,这个项目需要N 天才能完 ...

  2. redis 在windows 上的安装与使用

    1.redis-windows 最近在做一个抢拍模块,由于过于平凡的insert与update I/O受不了,故只好把东西放内存里,等拍卖结束了,在写入磁盘. 至于为什么要用window呢? 因为服务 ...

  3. linux 安装firefox

    从火狐官网下载的firefox-9.0.1.tar.bz2解压后,进入firefox文件夹,执行./firefox会提示缺少库,故采用yum安装Firefox9.1.切换到root用户 su - 2. ...

  4. [转载]JS、C#编码解码

    escape不编码字符有69个:*,+,-,.,/,@,_,0-9,a-z,A-Z encodeURI不编码字符有82个:!,#,$,&,',(,),*,+,,,-,.,/,:,;,=,?,@ ...

  5. [转载]c# 多线程一个带多个参数的方法

    比如我要线程一个private void subPing(int pre,int end) 我在Thread t=之后应该如何写 用匿名委托吧!那么简单为什么要这样写!t = new Thread(d ...

  6. 【POJ 3335】 Rotating Scoreboard (多边形的核- - 半平面交应用)

    Rotating Scoreboard Description This year, ACM/ICPC World finals will be held in a hall in form of a ...

  7. 179. Largest Number

    题目: Given a list of non negative integers, arrange them such that they form the largest number. For ...

  8. UML各种图画法总结

    <UML 2.4.1 教程> http://www.sparxsystems.cn/resources/uml2_tutorial/ <UML总结(对九种图的认识和如何使用Ratio ...

  9. Hashtable与HashMap区别(2)

    提到hashtable,先要澄清两个问题hashCode与equals().Hashtable有容量和加载因子,容量相当于桶,因子相当于桶里的对象.而hashCode我们可以把它理解为桶的序号,所以H ...

  10. SGU185 - Two Shortest

    原题地址:http://acm.sgu.ru/problem.php?contest=0&problem=185 题目大意:给出一个无向图,求出从 1 到 n 的两条没有相同边的最短路径(允许 ...