bzoj2815 [ZJOI2012]灾难
(bzoj没有题面,题面复制自洛谷)
题目描述
阿米巴是小强的好朋友。
阿米巴和小强在草原上捉蚂蚱。小强突然想,果蚂蚱被他们捉灭绝了,那么吃蚂蚱的小鸟就会饿死,而捕食小鸟的猛禽也会跟着灭绝,从而引发一系列的生态灾难。
学过生物的阿米巴告诉小强,草原是一个极其稳定的生态系统。如果蚂蚱灭绝了,小鸟照样可以吃别的虫子,所以一个物种的灭绝并不一定会引发重大的灾难。
我们现在从专业一点的角度来看这个问题。我们用一种叫做食物网的有向图来描述生物之间的关系:
一个食物网有N个点,代表N种生物,如果生物x可以吃生物y,那么从y向x连一个有向边。
这个图没有环。
图中有一些点没有连出边,这些点代表的生物都是生产者,可以通过光合作用来生存; 而有连出边的点代表的都是消费者,它们必须通过吃其他生物来生存。
如果某个消费者的所有食物都灭绝了,它会跟着灭绝。
我们定义一个生物在食物网中的“灾难值”为,如果它突然灭绝,那么会跟着一起灭绝的生物的种数。
举个例子:在一个草场上,生物之间的关系是:
如果小强和阿米巴把草原上所有的羊都给吓死了,那么狼会因为没有食物而灭绝,而小强和阿米巴可以通过吃牛、牛可以通过吃草来生存下去。所以,羊的灾难值是1。但是,如果草突然灭绝,那么整个草原上的5种生物都无法幸免,所以,草的灾难值是4。
给定一个食物网,你要求出每个生物的灾难值。
输入输出格式
输入格式:
输入文件 catas.in 的第一行是一个正整数 N,表示生物的种数。生物从 1 标
号到 N。
接下来 N 行,每行描述了一个生物可以吃的其他生物的列表,格式为用空
格隔开的若干个数字,每个数字表示一种生物的标号,最后一个数字是 0 表示列
表的结束。
输出格式:
输出文件catas.out包含N行,每行一个整数,表示每个生物的灾难值。
输入输出样例
5
0
1 0
1 0
2 3 0
2 0
4
1
0
0
0
说明
【样例说明】
样例输入描述了题目描述中举的例子。
【数据规模】
对50%的数据,N ≤ 10000。
对100%的数据,1 ≤ N ≤ 65534。
输入文件的大小不超过1M。保证输入的食物网没有环。
复制老师给的题解:
首先知道一个点至多有一个点使得那个点删除后直接影响到该点的,所以可以想到树形结构,也就是建立一棵“灭绝树”,“灭绝树”满足以下性质:对于一棵多叉树的任意一个结点,当它“灭绝”时,它所有的后代也会跟着“灭绝”。如何建立呢?
首先利用拓扑序顺序进行操作,因为在前面的点可以影响到后面的点,而做到后面的点的时候前面的点已经处理完毕了,然后利用图的反向图,该点在灭绝树中的父亲是在反向图中所有儿子的LCA,因为只有LCA灭绝了才可以导致该点直接灭绝,那么最后答案显然就是一个点在灭绝树中的子树大小,由于可能有多个根节点,所以我们假设一个超级点为0,如果一个点入度为0则连向0,由0跑DFS求size(子树个数),最后size要-1。
刚开始不知道lca怎么搞,上网看了一下以为要lct有点怕,后来发现虽然树在变,但还是可以倍增乱搞。
1 program catas(input,output); 2 type 3 etype=record 4 t,next:longint; 5 end; 6 var 7 e:array[0..10000000]of etype; 8 a,rea,r,d,q,ans:array[0..100010]of longint; 9 f:array[0..100010,0..18]of longint; 10 n,i,j,k,x,cnt,h,t:longint; 11 procedure add1(x,y:longint); 12 begin 13 inc(cnt);e[cnt].t:=y;e[cnt].next:=a[x];a[x]:=cnt; 14 end; 15 procedure add2(x,y:longint); 16 begin 17 inc(cnt);e[cnt].t:=y;e[cnt].next:=rea[x];rea[x]:=cnt; 18 end; 19 function lca(x,y:longint):longint; 20 begin 21 if d[x]<d[y] then begin k:=x;x:=y;y:=k; end; 22 for k:=16 downto 0 do if d[f[x,k]]>=d[y] then x:=f[x,k]; 23 if x=y then exit(x); 24 for k:=16 downto 0 do if f[x,k]<>f[y,k] then begin x:=f[x,k];y:=f[y,k]; end; 25 exit(f[x,0]); 26 end; 27 begin 28 assign(input,'catas.in');assign(output,'catas.out');reset(input);rewrite(output); 29 readln(n); 30 fillchar(r,sizeof(r),0); 31 fillchar(a,sizeof(a),0);fillchar(rea,sizeof(rea),0);cnt:=0; 32 for i:=1 to n do begin read(x);while x<>0 do begin add1(x,i);add2(i,x);inc(r[i]);read(x); end; end; 33 h:=0;t:=0;d[0]:=0; 34 for i:=1 to n do if r[i]=0 then begin inc(t);q[t]:=i;d[i]:=1;for j:=0 to 16 do f[i,j]:=0; end; 35 while h<t do 36 begin 37 inc(h);i:=a[q[h]]; 38 while i<>0 do 39 begin 40 dec(r[e[i].t]); 41 if r[e[i].t]=0 then 42 begin 43 inc(t);q[t]:=e[i].t; 44 j:=rea[e[i].t];x:=e[j].t;j:=e[j].next; 45 while j<>0 do begin x:=lca(x,e[j].t);j:=e[j].next; end; 46 f[e[i].t,0]:=x;d[e[i].t]:=d[x]+1;x:=e[i].t; 47 for j:=1 to 16 do f[x,j]:=f[f[x,j-1],j-1]; 48 end; 49 i:=e[i].next; 50 end; 51 end; 52 for i:=1 to n do ans[i]:=1; 53 for i:=n downto 1 do inc(ans[f[q[i],0]],ans[q[i]]); 54 for i:=1 to n do writeln(ans[i]-1); 55 close(input);close(output); 56 end.