ZOJ3965 Binary Tree Restoring

ZOJ3965 给定一颗二叉树的两种DFS序列 输出一种可能的二叉树的结构。

考察树的递归性质,不要想的太复杂。

当前节点在两个串中后面的节点假如不同则能确认两个子树,如果相同则把下个点作当前点的一个儿子。如果子树中还有未连根的点则接到当前点下。son数组表示每个点的子树有多少个点。pos数组记录每个数在每个序列中的位置。dfs中p1,p2指向同一个数

lim1,lim2表示当前点子树可能最大的子树范围。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<vector>


using namespace std;  
#define maxn 110000  
int n,fa[maxn];  
int s1[maxn],s2[maxn];  
int pos1[maxn],pos2[maxn];  
int vis[maxn],son[maxn];  
void dfs(int p1,int p2,int lim1,int lim2)  
{  
    //printf("%d %d %d %d\n:::::\n",p1,lim1,p2,lim2);  
    //system("pause");  
    int now=s1[p1];  
    if(vis[now]) return;  
    vis[now]=1;  
    if(p1<=0||p1>n) return ;  
    if(p2<=0||p2>n) return ;  
    if(lim1<=0) return ;  
    if(lim2<=0) return ;  
    if(p1>lim1||p2>lim2) return;  
    son[now]=1;  
    if(lim1==p1||lim2==p2) return;  
    int r1=lim1,r2=lim2;  
    if(s1[p1+1]!=s2[p2+1]&&p1+1<=lim1&&p2+1<=lim2)  
    {  
        int len=0;  
        if(!fa[s1[p1+1]])  
        {  
            fa[s1[p1+1]]=now;  
            r1=pos1[s2[p2+1]]-1;  
            len=r1-p1;  
            dfs(p1+1, pos2[ s1[p1+1] ] , r1 ,pos2[ s1[p1+1] ]+len-1  );  
            son[now]+=son[ s1 [p1+1] ];  
        }  
        if(!fa[s2[p2+1]])  
        {  
        fa[s2[p2+1]]=now;  
        r2=pos2[s1[p1+1]]-1;  
        len=r2-p2;  
        dfs( pos1[s2[p2+1]] , p2+1, pos1[s2[p2+1]]+len-1, r2 );  
        son[now]+=son[ s2 [p2+1] ];  
        }  
    }  
    else if(s1[p1+1]==s2[p2+1]&&p1+1<=lim1&&p2+1<=lim2)  
    {  
        fa[ s1[p1+1] ] = now;  
        dfs(p1+1,p2+1,lim1,lim2);  
        son[now]+=son[ s1[p1+1] ];  
        int nt=p1+son[s1[p1+1]]+1;  
        if(son[now]<lim1-p1+1)  
        {  
            fa[s1[nt]]=now;  
            dfs(nt,pos2[s1[nt]],lim1,lim2);  
            son[now]+=son[s1[nt]];  
        }  
    }  
}  
  
int main()  
{  
    int cas;  
    scanf("%d",&cas);  
    while(cas--)  
    {  
        scanf("%d",&n);  
        memset(fa,0,sizeof(fa));  
        memset(vis,0,sizeof(vis));  
        memset(son,0,sizeof(son));  
        memset(s1,0,sizeof(s1));  
        memset(s2,0,sizeof(s2));  
        memset(pos1,0,sizeof(pos1));  
        memset(pos2,0,sizeof(pos2));  
        for(int i=1;i<=n;i++) scanf("%d",&s1[i]),pos1[s1[i]]=i;  
        for(int i=1;i<=n;i++) scanf("%d",&s2[i]),pos2[s2[i]]=i;  
        dfs(1,1,n,n);  
        for(int i=1;i<n;i++) printf("%d ",fa[i]);  
        printf("%d\n",fa[n]);  
    }  
    return 0;  
}  

  

转载于:https://www.cnblogs.com/heisenberg-/p/6777225.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值