Cells UVALive - 3486(dfs序+手动开栈)

给一棵树,每次每次询问一个点是否是另一个点的祖先?

输入时是每个下标对应节点的儿子的数量

用dfs序 时间戳。。

如果一个点是另一个点的祖先,那么它的两个标记一定在祖先的范围之内

#include <iostream>
#include <cstdio>
#include <sstream>
#include <cstring>
#include <map>
#include <set>
#include <vector>
#include <stack>
#include <queue>
#include <algorithm>
#include <cmath>
#define rap(a, n) for(int i=a; i<=n; i++)
#define MOD 2018
#define LL long long
#define ULL unsigned long long
#define Pair pair<int, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define _  ios_base::sync_with_stdio(0),cin.tie(0)
//freopen("1.txt", "r", stdin);
using namespace std;
const int maxn = 20022000, INF = 0x7fffffff;
int r[maxn], l[maxn], sum[333333], zstack[maxn];
bool vis[maxn];
int dfs_clock, top, k, n, m, x, y;
void dfs()
{
    mem(vis, 0);
    dfs_clock = zstack[top=1] = 0;
    while(top > 0)
    {
        k = zstack[top];    //stack里存了结点  赋值给k后 k及对应了输入时的下标 即如果k<n 可以判定是否在输入的时候说了它有几个儿子
        if(!vis[k])
        {
            vis[k] = 1, l[k] = ++dfs_clock;
            if(k < n)
                for(int i=k==0?1:sum[k-1]+1; i<=sum[k]; i++) zstack[++top] = i;
        }
        else
            r[k] = ++dfs_clock, top--;
    }
}


int main()
{
    int T, kase = 0;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%d", &n);
        for(int i=0; i<n; i++)
        {
            int tmp;
            scanf("%d", &tmp);
            sum[i]=i==0?tmp:sum[i-1] + tmp;   //每个下标对应的前缀和 即为当前节点的最后一个儿子的值
        }
        dfs();
        printf("Case %d:\n", ++kase);
        scanf("%d",&m);
        while (m--){
            scanf("%d%d",&x,&y);
            if (l[x]<l[y] && r[x]>r[y]) puts("Yes");
                else puts("No");
        }
        if(T) cout<<endl;
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/WTSRUVF/p/9362127.html