zoj 2615 Cells 栈的运用

时间:2022-01-23 20:18:43

题目链接:ZOJ - 2615

Scientists are conducting research on the behavior of a newly discovered Agamic Cellular Microbe. This special kind of microbe is capable of massively reproducing by itself in a short time. The lifetime of an ACM consists of three phases:
1. The infancy phase, which starts from its birth and lasts for approximately several seconds;
2. The multiplication phase, in which one ACM can procreate up to 100 offspring in only several milliseconds;
3. The mature phase, in which it remains inactive for the rest of its life.

At the beginning of the experiment, a newborn, single cell of ACM, is
put into a suitable circumstance for its production. This cell,
numbered as 0, starts to multiply and its descendants are numbered,
starting from 1, according to their positions in the family hierarchy.
During the experiment special equipment is used to record the numbers of
the offspring generated by each of the ACM's. The experiment is stopped
after a certain time period.

zoj 2615 Cells 栈的运用

Your task is to help the scientists to determine whether one ACM is an ancestor of another.

Input Description

Standard input will contain multiple test cases. The first line of the input is a single integer T (1 <= T <= 10) which is the number of test cases. T test cases follow, each preceded by a single blank line.

Each test case starts with a single integer N (1 <= N <= 300,000) which is the number of ACM's that have their descendants recorded. The following N integers (not necessarily on a same line), Ci (0 <= i < N, 0 <= Ci <= 100), give the number of offspring of the i-th ACM. The next line contains an integer M (1 <= M <= 1,000,000) which is the number of queries. M lines follow, each contains two integers a and b, querying whether the a-th ACM is an ancestor of the b-th ACM.

The total number of ACM's may be greater than N, but would never exceed 20,000,000.

Output Description

Results should be directed to standard output. Start each case with "Case #:" on a single line, where # is the case number starting from 1. Two consecutive cases should be separated by a single blank line. No blank line should be produced after the last test case.

For each query, print either "Yes" or "No" on a single line, which is the answer to the query.

题意描述:给出一棵树,然后M个询问,每个询问u,v,判断u是否是v的祖先。

算法分析:刚开始看到这道题的时候,立马想到了LCA,于是快速找到LCA的模板并敲上,检查一下,交之,Segmentation Fault (哇,这是ZOJ独有的Judge结果),后来又改了改,交之,MLE,无语中。。。看到别人的想法是运用栈和dfs来处理即可了,给每个节点搞两个时间戳:第一次访问的时间戳和第二次访问(可以想象dfs中回溯的思想)的时间戳,然后通过时间戳来判断是否为祖先。效率上挺快的,又学习了一课。

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<stack>
#define inf 0x7fffffff
using namespace std;
const int maxn=+;
const int M = +; int n,m,pre[M],bac[M],vis[M],dfs_clock;
int an[maxn],c[maxn],sum;
stack<int> S; void dfs()
{
memset(vis,,sizeof(vis));
while (!S.empty()) S.pop();
S.push();
while (!S.empty())
{
int u=S.top() ;
if (vis[u]==)
{
vis[u]=;
pre[u]= ++dfs_clock;
for (int i=an[u]+ ;i<=an[u]+c[u] ;i++)
{
if (i<n) S.push(i);
else {
pre[i]= ++dfs_clock;
bac[i]= ++dfs_clock;
}
}
}
else if (vis[u]==)
{
bac[u]= ++dfs_clock;
S.pop();
}
}
} int main()
{
int t,ncase=;
int ok=;
scanf("%d",&t);
while (t--)
{
if (ok) printf("\n");ok=;
printf("Case %d:\n",ncase++);
memset(pre,,sizeof(pre));
memset(bac,,sizeof(bac));
memset(an,,sizeof(an));
memset(c,,sizeof(c));
sum=;
dfs_clock=;
int a,b;
scanf("%d",&n);
for (int i= ;i<n ;i++)
{
scanf("%d",&c[i]);
an[i]=sum;
sum += c[i];
}
dfs();
scanf("%d",&m);
while (m--)
{
scanf("%d%d",&a,&b);
if (pre[a]<pre[b] && bac[a]>bac[b]) printf("Yes\n");
else printf("No\n");
}
}
return ;
}