用bfs求dfs序(先序遍历序)

给你一棵树
求这棵树的dfs序
但是树的深度会爆系统栈
那么如何求出dfs序?
当然,空间足够
一般情况下有两种做法
1. 手写栈跑dfs
2. 跑bfs
第一种太过简单
我不予简介
我们主要说第二种
首先我们知道dfs序就是要先遍历左子树
那么我们是不是可以用一种神奇的方法
在bfs序的基础上做出dfs序
首先
我们知道
无论是dfs序还是bfs序
根节点一定在第一个位置
同时bfs序可得出一个分层结构
正序遍历bfs序到当前点时,当前点的父亲一定被遍历过
那么我们可以这样考虑
是否可以通过父亲的位置来求出当前点的位置?
答案是肯定的啊
dfs序中同一深度的儿子顺序和bfs序中相同
同一父亲的不同儿子在dfs序中位置值相差的数值
是以两儿子中较左儿子为根的子树的节点的数量
那么我们就可以在bfs时维护一个size
然后遍历bfs序
维护一个last表示从上一个点推得的这一点应在的位置
如果当前点和前一个点父亲不同
那么last为当前点父亲的位置+1
如果当前点和前一个点父亲相同
那么last+=前一个点的size
遍历后就求出了dfs序!
代码如下

#include 
#include 
#include 
char getc()
{
    static const int LEN = 1<<15;
    static char buf[LEN],*S=buf,*T=buf;
    if(S == T)
    {
        T = (S=buf)+fread(buf,1,LEN,stdin);
        if(S == T)return EOF;
    }
    return *S++;
}
int read()
{
    static char ch;
    static int D;
    while(!isdigit(ch=getc()));
    for(D=ch-'0'; isdigit(ch=getc());)
        D=(D<<3)+(D<<1)+(ch-'0');
    return D;
}
int n,idx;
int to[2000000],next[2000000],head[1000001],
    q[1000001],fa[1000001],size[1000001],
    dfs[1000001],zz[1000001];
void add(int x,int y)
{
    to[++idx]=y;
    next[idx]=head[x];
    head[x]=idx;
    to[++idx]=x;
    next[idx]=head[y];
    head[y]=idx;
    return ;
}
void bfs()
{
    int l=0,r=0;
    q[r++]=1;
    while(l!=r)
    {
        int x=q[l++];
        size[x]=1;
        for(int i=head[x];i;i=next[i])
            if(to[i]!=fa[x])
            {
                fa[to[i]]=x;
                q[r++]=to[i];
            }
    }
    for(int i=n-1;i>=0;--i)
        size[fa[q[i]]]+=size[q[i]];
    return ;
}
int main()
{
    n=read();
    for(int i=1;iint a=read(),b=read();
        add(a,b);
    }
    bfs();
    dfs[1]=1;
    zz[1]=2;
    int last;
    for(int i=1;iif(fa[q[i]]!=fa[q[i-1]])
            last=zz[fa[q[i]]];
        else
            (last+=size[q[i-1]]);
        dfs[last]=q[i];
        zz[q[i]]=last+1;
    }
    for(int i=1;i<=n;++i)
        printf("%d\n",dfs[i]);
    return 0;
}

你可能感兴趣的:(搜索)