bzoj 2815 灭绝树

对于一个食物网(一个DAG),一个物种死亡后,某些物种就必然死亡,求出必然死亡的是那些物种。

灭绝树的另一种含义是:“灭绝树跟节点到节点u的路径上的节点由那些原图中从根节点到节点u的所有路径中都经过了的点“。

  1 /**************************************************************
  2     Problem: 2815
  3     User: idy002
  4     Language: C++
  5     Result: Accepted
  6     Time:424 ms
  7     Memory:14036 kb
  8 ****************************************************************/
  9
 10 #include <cstdio>
 11 #include <vector>
 12 #define maxn 65544
 13 #define maxp 17
 14 using namespace std;
 15
 16 int n;
 17 vector<int> g[maxn], vg[maxn], gg[maxn];
 18 int indgr[maxn], topo[maxn], topo_cnt;
 19 int anc[maxn][maxp+1], depth[maxn];
 20 int siz[maxn];
 21
 22
 23 void make_topo() {
 24     vector<int> stk;
 25     for( int i=1; i<=n; i++ )
 26         if( indgr[i]==0 ) stk.push_back(i);
 27     while( !stk.empty() ) {
 28         int u = stk.back();
 29         topo[++topo_cnt] = u;
 30         stk.pop_back();
 31         for( int t=0; t<g[u].size(); t++ ) {
 32             int v = g[u][t];
 33             indgr[v]--;
 34             if( indgr[v]==0 ) stk.push_back(v);
 35         }
 36     }
 37 }
 38
 39 int lca( int u, int v ) {
 40     if( depth[u]<depth[v] ) swap(u,v);
 41     int t = depth[u]-depth[v];
 42     for( int i=0; t; t>>=1,i++ )
 43         if( t&1 ) u=anc[u][i];
 44     if( u==v ) return u;
 45     for( int p=maxp; p>=0&&anc[u][0]!=anc[v][0]; p-- )
 46         if( anc[u][p]!=anc[v][p] ) u=anc[u][p], v=anc[v][p];
 47     return anc[u][0];
 48 }
 49
 50 void dfs( int u ) {
 51     siz[u] = 1;
 52     for( int t=0; t<gg[u].size(); t++ ) {
 53         int v = gg[u][t];
 54         dfs(v);
 55         siz[u] += siz[v];
 56     }
 57 }
 58
 59 void work() {
 60     make_topo();
 61     for( int i=1; i<=n; i++ ) {
 62         anc[i][0] = i;
 63         depth[i] = 1;
 64     }
 65     for( int i=1; i<=n; i++ ) {
 66         int u = topo[i];
 67         if( vg[u].size()==0 ) continue;
 68         int ca = vg[u][0];
 69         for( int t=1; t<vg[u].size(); t++ ) {
 70             int v = vg[u][t];
 71             ca = lca(ca,v);
 72         }
 73         gg[ca].push_back(u);
 74         anc[u][0] = ca;
 75         depth[u] = depth[ca]+1;
 76         for( int p=1; p<=maxp; p++ )
 77             anc[u][p] = anc[anc[u][p-1]][p-1];
 78     }
 79     dfs(n);
 80     for( int i=1; i<=n-1; i++ )
 81         printf( "%d\n", siz[i]-1 );
 82 }
 83
 84 int main() {
 85     scanf( "%d", &n );
 86     for( int v=1,u; v<=n; v++ ) {
 87         while(1) {
 88             scanf( "%d", &u );
 89             if( u==0 ) break;
 90             g[u].push_back(v);
 91             vg[v].push_back(u);
 92             indgr[v]++;
 93         }
 94     }
 95     for( int u=1; u<=n; u++ )
 96         if( indgr[u]==0 ) {
 97             g[n+1].push_back(u);
 98             vg[u].push_back(n+1);
 99             indgr[u]++;
100         }
101     n++;
102     work();
103 }

时间: 2024-10-09 06:35:07

bzoj 2815 灭绝树的相关文章

bzoj 2815 灾难

首先假设我们定义x灭绝后y会灭绝,那么离y最近的x就为y的父亲节点,那么如果我们可以求出每个节点的父亲节点,我们就得到了一棵树,然后每个节点的灾难值就是子树的大小-1. 我们将出度数为0的节点的父亲节点定义为0,那么我们可以发现,某个点的父亲节点就是他所有儿子的父亲节点的lca. 备注:lca写错了,查了半天. //By BLADEVIL #include <cstdio> #include <cstring> #include <algorithm> #define

灾难 bzoj 2815

灾难(1s 128MB)catas [样例输入] 5 0 1 0 1 0 2 3 0 2 0 [样例输出] 4 1 0 0 0 题解: 主要算法:拓扑排序:最近公共祖先(Lca): 先跑出拓扑序 我们按拓扑序建立一棵"灭绝树" 灭绝树含义是当一个点灭绝时,它的子树将会全部灭绝 所以答案就是点在灭绝树中的子树大小 一个点如果灭绝,那么需要所有指向它的点灭绝 由于拓扑序的关系,指向它的点已经加入过了"灭绝树"中 所以这个点要灭绝,就需要所有指向它的点全部灭绝,即这些点的

BZOJ 3083 遥远的国度 树链剖分

3083: 遥远的国度 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 797  Solved: 181[Submit][Status] Description 描述 zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度.当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcwwzdjn的去路,他需要zcwwzdjn完成任务后才能进入遥远的国度继续追杀. 问题是这样的:遥远的国度有n个城市,这些城市之间由一些路连

bzoj 2815: [ZJOI2012]灾难

Description 阿米巴是小强的好朋友.阿米巴和小强在草原上捉蚂蚱.小强突然想,如果蚂蚱被他们捉灭绝了,那么吃蚂蚱的小鸟就会饿死,而捕食小鸟的猛禽也会跟着灭绝,从而引发一系列的生态灾难. 学过生物的阿米巴告诉小强,草原是一个极其稳定的生态系统.如果蚂蚱灭绝了,小鸟照样可以吃别的虫子,所以一个物种的灭绝并不一定会引发重大的灾难.我们现在从专业一点的角度来看这个问题.我们用一种叫做食物网的有向图来描述生物之间的关系: 一个食物网有 N个点,代表 N 种生物,如果生物 x 可以吃生物 y,那么从

【BZOJ 1036】树的统计Count(树链剖分)

[BZOJ 1036]树的统计Count(树链剖分) 1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 12991  Solved: 5233 Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成 一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权

BZOJ 2815 ZJOI 2012 灾难 动态倍增LCA

题目背景 阿米巴是小强的好朋友. 题目大意 给出一个食物链(拓扑图),定义一个生物所有的食物都灭绝了之后他自己也灭绝了.定义每种生物灭绝之后跟随着它灭绝的生物个数为这个生物的灾难值.求所有生物的灾难值. 思路 看题帽知出题人系列. fhq的题大家也知道,一般都是不可做的.于是我就去看了他的题解,发现这个题还是可做的. 定义一种灭绝树,对于任意一个子树,若这个子树的根节点灭绝,那么子树中的所有点都会灭绝.只要弄出这个树,我们就可以解决问题了. 先加一个超级食物,然后从这个点开始拓扑排序,保证处理到

BZOJ 2243 染色 | 树链剖分模板题进阶版

BZOJ 2243 染色 | 树链剖分模板题进阶版 这道题呢~就是个带区间修改的树链剖分~ 如何区间修改?跟树链剖分的区间询问一个道理,再加上线段树的区间修改就好了. 这道题要注意的是,无论是线段树上还是原树上,把两个区间的信息合并的时候,要注意中间相邻两个颜色是否相同. 这代码好长啊啊啊啊 幸好一次过了不然我估计永远也De不出来 #include <cstdio> #include <cstring> #include <algorithm> using namesp

hdu 6604 DAG上的支配树(灭绝树)

http://acm.hdu.edu.cn/showproblem.php?pid=6604 很裸的支配树/灭绝树题 一般图的tarjan算法的话,先建立,反向图,然后建立一个超级源点,然后连到几个起点,跑支配树就行 可惜太慢...过不去 #pragma GCC optimize("Ofast") #include<bits/stdc++.h> #define endl '\n' #define ll long long #define ull unsigned long

BZOJ 3531(树链剖分+线段树)

Problem 旅行 (BZOJ 3531) 题目大意 给定一颗树,树上的每个点有两个权值(x,y). 要求维护4种操作: 操作1:更改某个点的权值x. 操作2:更改某个点的权值y. 操作3:求a-->b路径上所有x属性与a,b相同的点y属性的和. 操作4:求a-->b路径上所有x属性与a,b相同的点y属性的最大值. N,Q ,x <= 10^5  ,  y <= 10^4 解题分析 由于x属性的范围较大,无法直接统计. 考虑每次修改为单点修改,询问时只对相同x属性的询问. 因此,