倍增lca-ZJOI2012 灾难
一个食物网有N个点,代表N种生物,如果生物x可以吃生物y,那么从y向x连一个有向边。这个图没有环。图中有一些点没有连出边,这些点代表的生物都是生产者,可以通过光合作用来生存; 而有连出边的点代表的都是消费者,它们必须通过吃其他生物来生存。如果某个消费者的所有食物都灭绝了,它会跟着灭绝。我们定义一个生物在食物网中的“灾难值”为,如果它突然灭绝,那么会跟着一起灭绝的生物的种数。现在请你求出每一个物种的“灾难值”。
首先思考:什么情况下一个物种会灭绝?也就是所有它能吃的东西灭绝了,它就灭绝了。所以如果要让物种A灭绝,我们可以选一个物种B,使得物种A所有能吃的东西都灭绝。我们定义”灭绝树”,其中一个节点的父亲是能让它灭绝的深度最低的结点。不难发现灭绝树上A的祖先灭绝后,A一定灭绝。所以若要让物种x,y一起灭绝,只需查询它们所有父亲在灭绝树上的lca即可。
这道题做了三天。。最后用cyaron对拍出来,发现是一个以前写的模块忘记改回来了。。以后写程序就要一口气写完,不要被外界干扰。
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
using namespace std; const int maxn=; int first1[maxn], first2[maxn], topo[maxn], topo2[maxn], out[maxn];
int fa[maxn][], dep[maxn], size[maxn], ans[maxn];
struct Edge{
int v, to, next;
};
Edge edges1[maxn], edges2[maxn]; int n, cnte1, cnte2; void addedge(int *first, Edge *edges, int &cntedge,
int v, int from, int to){
edges[cntedge].v=v;
edges[cntedge].to=to;
edges[cntedge].next=first[from];
first[from]=cntedge;
cntedge++;
return;
} double log2(int x){
return log(x)/log();
} int get_lca(int x, int y){
int t=, step=;
if (dep[x]<dep[y]) swap(x, y);
t=dep[x]-dep[y];
while (t){
if (t&) x=fa[x][step];
t>>=;
++step;
}
for (int step=; step>; --step){
if (fa[x][step]!=fa[y][step]){
x=fa[x][step];
y=fa[y][step];
}
}
if (x!=y) x=fa[x][];
return x;
} int main(){
for (int i=; i<maxn; ++i) first1[i]=first2[i]=-;
scanf("%d", &n);
for (int i=; i<=n; ++i){
int t;
scanf("%d", &t);
while (t) {
addedge(first1, edges1, cnte1, , i, t);
addedge(first2, edges2, cnte2, , t, i);
++out[i];
scanf("%d", &t);
}
}
queue<int> q;
for (int i=; i<=n; ++i){
if (!out[i]){
addedge(first1, edges1, cnte1, , i, );
addedge(first2, edges2, cnte2, , , i);
out[i]=;
}
}
//以上:读入、加边
q.push();
int nownode, nowedge, nowson;
for (int i=; i<=n; ++i){
nownode=q.front();
q.pop();
topo[i]=nownode;
nowedge=first2[nownode];
while (nowedge!=-){
nowson=edges2[nowedge].to;
if (!--out[nowson]){
q.push(nowson);
}
nowedge=edges2[nowedge].next;
}
}
//以上:拓扑排序
int lca=, cur=;
for (int i=; i<=n; ++i){
nownode=topo[i];
nowedge=first1[nownode];
lca=nowson=edges1[nowedge].to;
nowedge=edges1[nowedge].next;
while (nowedge!=-){
nowson=edges1[nowedge].to;
//if (!nowedge) break; !!!!
lca=get_lca(lca, nowson);
nowedge=edges1[nowedge].next;
}
dep[nownode]=dep[lca]+;
cur=;
fa[nownode][cur]=nownode;
fa[nownode][++cur]=lca;
++size[lca];
while (fa[nownode][cur]){
fa[nownode][cur+]=fa[fa[nownode][cur]][cur];
++cur;
}
}
//以上:建立灭绝树
while (!q.empty()) q.pop();
for (int i=; i<=n; ++i){
ans[i]=;
if (size[i]==) q.push(i);
}
int fath;
for (int i=n; i>; --i){
nownode=q.front();
q.pop();
fath=fa[nownode][];
--size[fath];
if (!size[fath]) q.push(fath);
ans[fath]+=ans[nownode];
}
//以上:统计size
for (int i=; i<=n; ++i)
printf("%d\n", ans[i]-);
return ;
}
附:用来对拍的python程序。
from cyaron import *
from random import randint for n in range(5, 11):
input_io = IO()
for i in range(0, 100):
#对于n,生成100个数据。
input_io.input_writeln(n)
print(n) ###
topo = Vector.random(n, [(1, n)], 0)
for j in topo:
print(j, end=' ') ###
#拓扑序
print() ###
m = randint(n*2, n*3)
#有多少个边(有一些边会被舍弃掉)
out = []
for j in range(0, n):
out.append(0)
#每个结点的出度(吃什么)
for j in range(0, m):
t = randint(0, n-1)
if out[t] < t / 2:
out[t] += 1
graph = []
for j in range(0, n):
graph.append([])
for j in range(1, n):
#对于每一个结点
use = []
#连了哪些结点
for k in range(0, n):
use.append(0)
for k in range(0, out[j]):
#对于要连的边
node = randint(0, j-1)
while use[node] == 1:
node = randint(0, j-1)
use[node] = 1
#选一个点
graph[topo[j][0]-1].append(topo[node][0])
for j in graph:
for k in j:
#print(k, end=" ")
input_io.input_write(k)
#print(0)
input_io.input_writeln(0)
Compare.program("mine.exe", input=input_io,
std_program="yangs.exe", stop_on_incorrect=True)
倍增lca-ZJOI2012 灾难的更多相关文章
- Luogu_2597_[ZJOI2012]灾难 倍增lca + 构造
Luogu_2597_[ZJOI2012]灾难 倍增lca + 构造 题意: 我们用一种叫做食物网的有向图来描述生物之间的关系:一个食物网有N个点,代表N种生物,如果生物x可以吃生物y,那么从y向x连 ...
- 【bzoj2815】[ZJOI2012]灾难 拓扑排序+倍增LCA
题目描述(转自洛谷) 阿米巴是小强的好朋友. 阿米巴和小强在草原上捉蚂蚱.小强突然想,果蚂蚱被他们捉灭绝了,那么吃蚂蚱的小鸟就会饿死,而捕食小鸟的猛禽也会跟着灭绝,从而引发一系列的生态灾难. 学过生物 ...
- P2597 [ZJOI2012]灾难——拓扑,倍增,LCA
最近想学支配树,但是基础还是要打好了的: P2597 [ZJOI2012]灾难 这道题是根据食物链链接出一个有向图的关系,求一个物种的灭绝会连带几种物种的灭绝: 求得就是一个点能支配几个点: 如果一个 ...
- 【BZOJ2815】[ZJOI2012]灾难 拓扑排序+LCA
[BZOJ2815][ZJOI2012]灾难 题目描述 阿米巴是小强的好朋友. 阿米巴和小强在草原上捉蚂蚱.小强突然想,果蚂蚱被他们捉灭绝了,那么吃蚂蚱的小鸟就会饿死,而捕食小鸟的猛禽也会跟着灭绝,从 ...
- [洛谷P2597] [ZJOI2012]灾难
洛谷题目链接:[ZJOI2012]灾难 题目描述 阿米巴是小强的好朋友. 阿米巴和小强在草原上捉蚂蚱.小强突然想,如果蚂蚱被他们捉灭绝了,那么吃蚂蚱的小鸟就会饿死,而捕食小鸟的猛禽也会跟着灭绝,从而引 ...
- 1321. [ZJOI2012] 灾难
1321. [ZJOI2012] 灾难 ★★☆ 输入文件:catas.in 输出文件:catas.out 简单对比时间限制:1 s 内存限制:128 MB [问题描述] 阿米巴是小强的 ...
- 洛谷 P2597 [ZJOI2012]灾难 解题报告
P2597 [ZJOI2012]灾难 题目描述 阿米巴是小强的好朋友. 阿米巴和小强在草原上捉蚂蚱.小强突然想,如果蚂蚱被他们捉灭绝了,那么吃蚂蚱的小鸟就会饿死,而捕食小鸟的猛禽也会跟着灭绝,从而引发 ...
- [板子]倍增LCA
倍增LCA板子,没有压行,可读性应该还可以.转载请随意. #include <cstdio> #include <cstring> #include <algorithm ...
- 洛谷P3128 [USACO15DEC]最大流Max Flow [倍增LCA]
题目描述 Farmer John has installed a new system of pipes to transport milk between the stalls in his b ...
- Gym100685G Gadget Hackwrench(倍增LCA)
题目大概说一棵边有方向的树,q个询问,每次询问结点u是否能走到v. 倍增LCA搞即可: 除了par[k][u]表示u结点往上走2k步到达的结点, 再加上upp[k][u]表示u结点往上走2k步经过边的 ...
随机推荐
- string(未完待续)
1.string字符串的长度 可以用 a.length() 来测,或者是a.size() 来测 不可以用strlen(a)来求其长度, sizeof(a)是固定值16, 求的是strin ...
- CodeForces Gym 100228 Graph of Inversions
题目大意 对于一个长为$N$的序列$A$,定义它所对应的逆序图: 有$N$个点组成,标号为$1...N$的无向图,对于每一组$i,j(i<j)$若存在$A_i>A_j$则在新图中就存在一条 ...
- ACM学习历程—POJ3565 Ants(最佳匹配KM算法)
Young naturalist Bill studies ants in school. His ants feed on plant-louses that live on apple trees ...
- Gson小记
Gson过滤字段,只要在字段前面添加“transient”关键字即可:之前就是因为Channel字段序列化的时候导致了stack over异常.
- 使用ceph命令提示handle_connect_reply connect got BADAUTHORIZER
输入命令提示如下错误: [root@node1 ~]# rados -p testpool ls 2017-10-21 06:13:25.743045 7f8f89b6d700 0 -- 192.16 ...
- AVI编码器
AVI编码器,AVI英文全称为Audio Video Interleaved,即音频视频交错格式.就是编码语音和影像同步组合在一起的文件格式.它对视频文件采用了一种有损压缩方式,但压缩比较高,因此尽管 ...
- chef语法和案例
1. 添加用户 $ vim create_user.rb -----------------------------------> user 'charlie' do //创建一个uid为88的 ...
- Linux部署walle
背景:Walle 一个web部署系统工具,配置简单.功能完善.界面流畅.开箱即用!支持git.svn版本管理,支持各种web代码发布,PHP,Python,JAVA等代码的发布.回滚,可以通过web来 ...
- js页面跳转常用的几种方式(转)
js页面跳转常用的几种方式 转载 2010-11-25 作者: 我要评论 js实现页面跳转的几种方式,需要的朋友可以参考下. 第一种: 复制代码代码如下: <script langu ...
- Command line option syntax error. Type Command /? for Help.
--------------------------- Microsoft Visual C++ 2005 Redistributable --------------------------- Co ...