1135 Is It A Red-Black Tree (30 分)

\(30\)分的题目果然顶啊。

思路

根据先序中序建立一棵树

  1. 判断根结点是否是黑色。
  2. 根据建立的树,从根结点开始遍历,如果当前结点是红色,判断它的孩子节点是否为黑色。
  3. 从根节点开始,递归遍历,检查每个结点的左子树的高度和右子树的黑色结点的个数,比较个数集合大小是否为\(1\)
const int N=35;
unordered_map<int,PII> tree;
unordered_map<int,int> pos;
int pre[N],in[N];
int n;
set<int> S;
bool ok;

int build(int prel,int prer,int inl,int inr)
{
    if(!ok) return 0;
    if(prel > prer) return 0;

    int root=pre[prel];
    int k=pos[abs(root)];
    if(k<inl || k>inr)
    {
        ok=false;
        return 0;
    }
    int leftlen=k-inl;
    int lchild=build(prel+1,prel+leftlen,inl,k-1);
    int rchild=build(prel+leftlen+1,prer,k+1,inr);
    tree[root]={lchild,rchild};
    return root;
}

void dfs(int root,int cnt)
{
    if(root == 0)
    {
        S.insert(cnt);
        return;
    }

    if(root > 0)
    {
        dfs(tree[root].fi,cnt+1);
        dfs(tree[root].se,cnt+1);
    }
    else
    {
        dfs(tree[root].fi,cnt);
        dfs(tree[root].se,cnt);
    }
}

bool check(int root)
{
    if(root < 0) return false;

    queue<int> q;
    q.push(root);
    while(q.size())
    {
        int t=q.front();
        q.pop();

        S.clear();
        dfs(t,0);
        if(S.size() > 1) return false;

        if(tree[t].fi)
        {
            if(t < 0 && tree[t].fi < 0) return false;
            q.push(tree[t].fi);
        }
        if(tree[t].se)
        {
            if(t < 0 && tree[t].se < 0) return false;
            q.push(tree[t].se);
        }
    }
    return true;
}

int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        cin>>n;
        for(int i=0;i<n;i++)
        {
            cin>>pre[i];
            in[i]=abs(pre[i]);
        }

        sort(in,in+n);
        for(int i=0;i<n;i++) pos[in[i]]=i;

        ok=true;
        int root=build(0,n-1,0,n-1);

        if(ok) ok=check(root);
        
        if(ok) puts("Yes");
        else puts("No");
    }
    //system("pause");
    return 0;
}
posted @ 2021-03-03 20:03  Dazzling!  阅读(56)  评论(0编辑  收藏  举报