You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决树节点祖先判断程序的超时问题?

解决树祖先判断程序的超时问题

核心问题定位

你的代码超时的主要原因是邻接表构建错误:在处理每个节点的直接祖先时,重复执行了g[anchestors[i]].push_back(i);两次,还额外添加了反向边g[i].push_back(anchestors[i]);。这会导致每个父节点到子节点的边被存储3次,DFS遍历的时候会反复处理这些重复边,时间复杂度从O(n)飙升到O(n²),对于n=1e5的规模来说完全无法承受。

具体修复与优化方案

1. 修复邻接表构建逻辑

树是单向的父到子结构,构建邻接表时只需要添加父节点到子节点的单向边即可,不需要反向边,更不能重复添加:

for(int i=1; i<=n; ++i){
    readInt(anchestors[i]);
    if(anchestors[i] != 0) {
        // 仅添加父节点到子节点的单向边,消除冗余
        g[anchestors[i]].push_back(i);
    }else{
        start=i;
    }
}

2. 优化输入速度

把readInt里的getchar()替换为getchar_unlocked(),后者是无锁版本,输入速度更快(该函数在Linux环境下有效,绝大多数OJ均支持):

void readInt(int &n){
    char ch;
    int sign = 1;
    while(ch = getchar_unlocked(), isspace(ch));
    n = 0;
    if(ch == '-')
        sign = -1;
    else n = ch - '0';
    while(ch = getchar_unlocked(), isdigit(ch))
        n = (n << 3) + (n << 1) + ch - '0';
    n *= sign;
}

3. 优化输出速度

单个cout输出1e5次会产生较大开销,建议把所有查询结果先存入字符串,最后一次性输出:

// 替换原查询循环
string res;
res.reserve(q * 2); // 预分配空间,避免多次扩容
while(q--){
    readInt(u),readInt(v);
    res += isAnchestor(u,v) ? "1\n" : "0\n";
}
cout << res;

同时打开cin.tie(0);,取消cin与cout的同步绑定,进一步提升输出效率:

int main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0); // 取消注释该行
    cout.tie(0);
    // ... 其余代码
}

4. 修正DFS初始参数

根节点的parent应设为0(根节点无父节点,其祖先标记为0),避免出现逻辑错误:

dfs(start, 0);

5. 时间戳逻辑简化(可选)

当前time_out使用++Time的方式可以简化,进入节点时time_in[node] = ++Time,离开时time_out[node] = Time,区间逻辑保持左闭右闭,判断逻辑不变但减少一次自增操作:

void dfs(int node,int parent){
    time_in[node] = ++Time;
    for(int &to : g[node]){
        if(to != parent){
            dfs(to, node);
        }
    }
    time_out[node] = Time; // 此处无需++Time
}

完整修复后的代码示例

#include<iostream>
#include<vector>
#include<string>
using namespace std;

vector<vector<int>> g;
vector<int> time_in, time_out;
int Time = 0;

void dfs(int node, int parent) {
    time_in[node] = ++Time;
    for (int &to : g[node]) {
        if (to != parent) {
            dfs(to, node);
        }
    }
    time_out[node] = Time;
}

bool isAnchestor(int anch, int node) {
    return time_in[anch] <= time_in[node] && time_out[anch] >= time_out[node];
}

void readInt(int &n) {
    char ch;
    int sign = 1;
    while (ch = getchar_unlocked(), isspace(ch));
    n = 0;
    if (ch == '-')
        sign = -1;
    else
        n = ch - '0';
    while (ch = getchar_unlocked(), isdigit(ch))
        n = (n << 3) + (n << 1) + ch - '0';
    n *= sign;
}

int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    int n, start;
    readInt(n);
    time_in.resize(n + 1);
    time_out.resize(n + 1);
    g.resize(n + 1);
    vector<int> anchestors(n + 2);

    for (int i = 1; i <= n; ++i) {
        readInt(anchestors[i]);
        if (anchestors[i] != 0) {
            g[anchestors[i]].push_back(i);
        } else {
            start = i;
        }
    }

    dfs(start, 0);

    int q, u, v;
    readInt(q);
    string res;
    res.reserve(q * 2);
    while (q--) {
        readInt(u), readInt(v);
        res += isAnchestor(u, v) ? "1\n" : "0\n";
    }
    cout << res;

    return 0;
}

内容的提问来源于stack exchange,提问作者Isa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 04:30:15