DFS序 (非递归)

Posted zeronera

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了DFS序 (非递归)相关的知识,希望对你有一定的参考价值。

递归爆栈了,改了半天非递归的,记录一下

求以某个结点为根的子树中权值大于k的结点的数量

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1000010;
typedef long long ll;
int in[maxn], out[maxn], tim,p;
struct ss
{
    int id, st;
    ss(int _id = 0, int _st = 0) : id(_id), st(_st) {}
} sta[maxn];

struct node
{
    int v, next;
} edge[maxn << 1];
int head[maxn], cnt;
void add(int x, int y) //无向边开边数两倍大小 切记
{
    edge[++cnt].v = y;
    edge[cnt].next = head[x];
    head[x] = cnt;
}
void dfs(int u)
{
    in[u] = ++tim; 
    sta[p++] = ss(u,head[u]);
    while (p)
    {
        ss now = sta[p - 1];
        for (int i = now.st; i != 0;)
        {
            int nx = edge[i].v;
            if (!in[nx])
            {
                sta[p-1]=ss(now.id,edge[i].next);
                in[nx] = ++tim;
                sta[p++] = ss(nx,head[nx]);
                i = head[nx];
                now = sta[p - 1];
            }
            else
                i = edge[i].next;
        }
        out[sta[p - 1].id] = tim;
        p--;
    }
}
int T[maxn], L[maxn * 30], R[maxn * 30], sum[maxn * 30];
int sz[maxn], h[maxn];
int n, q, k, tot;

void build(int &rt, int l, int r) 
{
    rt = ++tot;
    sum[rt] = 0;
    if (l == r)
        return;
    int mid = (l + r) >> 1;
    build(L[rt], l, mid);
    build(R[rt], mid + 1, r);
}

void update(int &rt, int l, int r, int pre, int x)
{
    rt = ++tot;
    L[rt] = L[pre];
    R[rt] = R[pre];
    sum[rt] = sum[pre] + 1;
    if (l == r)
        return;
    int mid = (l + r) >> 1;
    if (x <= mid)
        update(L[rt], l, mid, L[pre], x);
    else
        update(R[rt], mid + 1, r, R[pre], x);
}
int query(int s, int e, int l, int r, int k) //区间小于等于k的数的个数
{
    if (l == r)
        return sum[e] - sum[s];
    int mid = (l + r) >> 1;
    if (k <= mid)
        return query(L[s], L[e], l, mid, k);
    else
        return sum[L[e]] - sum[L[s]] + query(R[s], R[e], mid + 1, r, k);
}
inline int read()
{
    int sgn = 1;
    int cnt = 0;
    char ch = getchar();
    while (ch < '0' || ch > '9')
    {
        if (ch == '-')
            sgn = -sgn;
        ch = getchar();
    }
    while ('0' <= ch && ch <= '9')
    {
        cnt = cnt * 10 + (ch - '0');
        ch = getchar();
    }
    return sgn * cnt;
}

int main()
{
    int n, u, v, x;
    n = read();
    for (int i = 1; i <= n; i++)
    {
        h[i] = read();
        h[i]++;
    }
    for (int i = 1; i <= n - 1; i++)
    {
        u = read();
        v = read();
        add(u, v);
        add(v, u);
    }
    dfs(1);
    for (int i = 1; i <= n; i++)
        sz[in[i]] = h[i];
    tot = 0;
    build(T[0], 1, maxn);
    for (int i = 1; i <= n; i++)
        update(T[i], 1, maxn, T[i - 1], sz[i]);
    q = read();
    while (q--)
    {
        x = read();
        k = read();
        k++;
        printf("%d
", query(T[in[x] - 1], T[out[x]], 1, maxn, k));
    }
    return 0;
}

以上是关于DFS序 (非递归)的主要内容,如果未能解决你的问题,请参考以下文章

层次遍历递归和非递归方法

广度优先遍历和深度优先遍历的真正区别

C++实现二叉树 前中后序遍历(递归与非递归)非递归实现过程最简洁版本

二叉树的前中后序递归和非递归遍历操作代码

二叉树的前序中序后序遍历-非递归-使用同一段代码实现

第三节.二叉树和分治法