【树的合并】CodeChef - TR2 Robot Game

Problem Description

N张地图,每个地图都是二叉树的结构。每个岛屿都有一个资本,这是它的地图的二叉树的根

她从这N张地图中选择了k张,并在每张地图的首府城市放置了一个机器人。每个机器人都由一个共同的控制字符串控制。如果控制字符串的当前字符是L(R),则所有机器人移动到其地图上的左(右)子树。所有机器人都遵循相同的控制字符串,并在各自的地图上移动。
对于选择k张,然你求最长的长度。假设n = 2, 让你求k = 1的时候的最长长度,k = 2的时候的最长长度。

思路:

就是把所有树合成一棵树,重叠的结点,记录重叠次数,求出各个重叠次数最深的点,就是字符串的长度。

代码:

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+100;//被这里坑惨了,题目没看出数据范围那么大,看了别人AC的数据范围都开那么大,一开就A了。
struct node
{
    int l, r;
    int cnt;
    inline void init()//初始化结点
    {
        l = r = -1;
        cnt = 0;
    }
};
node tree1[N], tree2[N];//合成后的树(主树),其他的树(次树)
int ans[N], top;
void Merge(int o, int root, int deep)//o是主树的根,root是次树的根
{
    tree1[o].cnt++;//重叠次数++
    ans[tree1[o].cnt] = max(ans[tree1[o].cnt], deep);//对应重叠次数,不断更新最大的深度
    if(tree2[root].r != -1)
    {
        if(tree1[o].r == -1)
        {
            tree1[o].r = ++top;
            tree1[tree1[o].r].init();
        }
        Merge(tree1[o].r, tree2[root].r, deep+1);
    }
    if(tree2[root].l != -1)
    {
        if(tree1[o].l == -1)
        {
            tree1[o].l = ++top;
            tree1[tree1[o].l].init();
        }
        Merge(tree1[o].l, tree2[root].l, deep+1);
    }
}
int main()
{
    int T, n, m, u, v;
    char c[5];
    scanf("%d", &T);
    while(T--)
    {
        memset(ans, 0, sizeof(ans));
        top = 1;
        scanf("%d", &n);
         for(int i = 0; i <= n; i++) tree1[i].init();//初始化 主树
        for(int j = 1; j <= n; j++)
        {
            scanf("%d", &m);
            for(int i = 0; i <= m; i++) tree2[i].init();//初始化 次树
            for(int i = 1; i < m; i++)
            {
               // printf("~\n");
                scanf("%d %s %d", &u, c, &v);
                if(c[0] == 'L') tree2[u].l = v;
                else tree2[u].r = v;
            }
            //printf("!\n");
            Merge(1, 1, 0);//合成
        }
        for(int i = 1; i <= n; i++)//输出
        {
            printf("%d", ans[i]);
            if(i == n) printf("\n");
            else printf(" ");
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值