2016 acm河南省赛 G Prototypes analyze



题意:二叉排序树(没叫错名吧),问有多少种不同形状的树(如图)。

题目分析:貌似是今年world final的原题(今年考了好多原题呀,各种没做过),大牛们说的前序遍历的方法没有听明白。这是我自己的理解。首先建二叉树,按数组递归的插入,建树的同时记录左右子树下有多少节点。对比时比较每个节点对应的左右节点个数是否相同,全相同就说明2个树长的一样,否则不一样。由于插入和查询都需要递归调用,时间复杂度貌似比较高,但是一共就50个树,最多1000个节点,随便搞一下都可以做出来。

//
//  main.cpp
//  Prototypes analyze
//
//  Created by teddywang on 16/6/8.
//  Copyright © 2016年 teddywang. All rights reserved.
//

#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

typedef struct node{
    node *left,*right;
    int l,r,num;
}trienode;
trienode *s[100];

void init(trienode *rt)
{
    rt->left=rt->right=NULL;
    rt->l=rt->r=rt->num=0;
}

void insert(trienode *rt,int m)
{
    trienode *r;
    if(m> rt->num )
    {
        rt->r++;
        if(rt->right==NULL)
        {
            
            r=new node;
            init(r);
            r->num=m;
            rt->right=r;
        }
        else insert(rt->right,m);
    }
    else
    {
        rt->l++;
        if(rt->left==NULL)
        {
            r=new node;
            init(r);
            r->num=m;
            rt->left=r;
        }
        else insert(rt->left,m);
    }
}

int cmp(trienode *a,trienode *b)
{
    int flag1=0,flag2=0;
    if(a->l!=b->l||a->r!=b->r) return 0;
    if(a->l==1||a->l==0)
        flag1=1;
    else flag1=cmp(a->left,b->left);
    if(a->r==1||a->r==0)
        flag2=1;
    else flag2=cmp(a->right,b->right);
    if(flag1==1&&flag2==1) return 1;
    else return 0;
}

int main()
{
    int m,n,N;
    cin>>N;
    while(N--)
    {
        cin>>n>>m;
        for(int i=0;i<n;i++)
        {
            s[i]=new node;
            init(s[i]);
            int t[100];
            cin>>t[0];
            s[i]->num=t[0];
            for(int j=1;j<m;j++)
            {
                cin>>t[j];
                insert(s[i],t[j]);
            }
        }
        int vis[100],ans=0;
        for(int i=0;i<n;i++)
        {
            int flag1=0;
            for(int j=i+1;j<n;j++)
            {
                if(!vis[j]&&cmp(s[i],s[j])==1)
                {
                    vis[j]=1;
                    flag1=1;
                }
            }
            if(flag1==0) ans++;
        }
        cout<<ans<<endl;
        for(int i=0;i<n;i++)
            free(s[i]);
    }
}


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值