树链剖分——为什么用链式前向星存图在dfs时会栈溢出,而用vector存图则不会?

新手上路,请多包涵

问题出现在树链剖分的dfs1和dfs2部分,首先是使用链式前向星存图的方式,已经判断出来会出现栈溢出。

//fa[x]为x的父节点,siz[x]为以x为根的子树大小,deep[x]为x的深度,son[x]为x的重儿子,top[x]为x所在重链顶,id[x]为x的dfs序,w[x]为X的权值。
struct EDGE{
    int to, next;
}edge[N << 1];
int head[N << 1], cnt = 0;

void add(int x, int y)
{
    edge[++cnt].to = y;
    edge[cnt].next = head[x];
    head[x] = cnt;
}
void dfs1(int x, int father)
{
    deep[x] = deep[father] + 1;
    fa[x] = father;
    siz[x] = 1;
    for(int i = head[x]; i; i = edge[i].next)
    {
        int y = edge[i].to;
        if(y != father)
        {
            fa[y] = x;
            dfs1(y, x);
            siz[x] += siz[y];
            if(!son[x] || siz[son[x]] < siz[y])
                son[x] = y;
        }
    }
}

void dfs2(int x, int topx)
{
    id[x] = ++num;
    w_new[num] = w[x];
    top[x] = topx;
    if(!son[x])
        return;
    dfs2(son[x], topx);
    for(int i = head[x]; i; i = edge[i].next)
    {
        int y = edge[i].to;
        if(y != fa[x] && y != son[x])
            dfs2(y, y);
    }
}
void init()
{
    for(int i = 0; i < (N << 1); i++)
        edge[i].next = head[i] = 0;
    for(int i = 0; i <= N; i++)
        son[i] = id[i] = fa[i] = deep[i] = siz[i] = top[i] = 0;
    cnt = 0;
}
void solve()
{
    cin >> n >> m;
    for(int i = 1; i <= n; i++)
        cin >> w[i];
    for(int i = 1; i < n; i++)
    {
        int x, y;
        cin >> x >> y;
        add(x, y);
        add(y, x);
    }
    init();
    //涉及出错部分如上
}

下面是使用vector存图的部分,不会出现栈溢出。

struct Graph{
    vector<vector<int> > table;
    void init(int _n) { table.assign(_n + 1, {}); }
    void add(int u, int v)
    {
        table[u].push_back(v);
    }
}G;

void dfs1(int x, int father)
{
    deep[x] = deep[father] + 1;
    fa[x] = father;
    siz[x] = 1;
    for (int v : G.table[x])
    {
        if (v == father) continue;
        dfs1(v, x);
        siz[x] += siz[v];
        if (siz[v] > siz[son[x]])
            son[x] = v;
    }
}

void dfs2(int x, int topx)
{
    id[x] = ++num;
    w_new[num] = w[x];
    top[x] = topx;
    if(!son[x])
        return;
    dfs2(son[x], topx);
    for (int v : G.table[x])
    {
        if (v == fa[x] || v == son[x])
            continue;
        dfs2(v, v);
    }
}
void init()
{
    num = 0;
    for (int i = 0; i <= n; ++i)
    {
        son[i] = id[i] = fa[i] = deep[i] = siz[i] = top[i] = 0;
        tag[i] = 0;
    }
    G.init(n);
}

void solve()
{
    cin >> n >> m;
    for(int i = 1; i <= n; i++)
        cin >> w[i];
    init();
    for(int i = 1; i < n; i++)
    {
        int x, y;
        cin >> x >> y;
        G.add(x, y);
        //cout << 1 << endl;
        G.add(y, x);
    }
}
阅读 715
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题