code#5 P4 逻辑树

Posted ztz11

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了code#5 P4 逻辑树相关的知识,希望对你有一定的参考价值。

 

时间限制: 3.0 秒

空间限制: 512 MB

相关文件: 题目目录

题目描述

有一棵树,叫逻辑树。

这个树有根,有 2N1 个节点,其中 N 个叶子,每个非叶节点恰好有两个孩子。

每个叶子上有一个 01 变量,它的取值可能为 True 或 False。每个非叶节点上有一个逻辑运算符,这个运算可能为 AND 或者 OR。

一个非叶节点的取值定义为它两个儿子的取值,作这个节点上的运算得到的结果。

有一个黑恶势力想知道这个树的根节点的取值,他准备了一个长度为 N 的询问序列 {Pi},每个叶子在这个序列中恰好出现一次。

黑恶势力会依次询问这些叶子的值,但是,如果他发现某一次询问是不必要的,那么他会跳过这个无意义的询问(为了帮助理解,考虑 x AND y 在我们知道 x 为 False 之后,不必知道 y 的值就可推算 x AND y 的值)。

当然,邪恶总是能战胜正义,黑恶势力总能达到他的目的。但是我们可以拖慢他的节奏,你现在可以安排每个叶子的权值,使得黑恶势力询问的次数尽可能多,在此基础上,我们希望这个树的根节点取值尽量为 True。

请你计算一组解,任何一种合法方案都是可以接受的。

输入格式

从标准输入读入数据。

第一行一个整数 N,意义如题面所示。

接下来一行 N1 个整数,第 i 个数代表节点 N+i 上的运算符,其中 0 表示 AND1 表示 OR

接下来 2N2 行,每行两个整数u,v,描述一条u,v之间的边。

最后一行 N 个整数,表示黑恶势力的询问序列。

你可以认为 1N 是叶子,N+12N1 是非叶节点,且 N+1 是根,输入数据保证每个非叶节点有两个孩子。

输出格式

输出到标准输出。

输出一个长度为 N 的 01串 S,其中 Si 表示第 i 个叶子的取值,0 为 False, 1 为 True.

思路:

显然这是一个特殊地树形DP

我们首先将树上每个节点的儿子都处理出来

然后从根节点跑第一遍DFS

然后我们就可以通过询问的次序,处理出这个点被查到的先后

当然为了尽可能不让黑帮老大猜到,我们会按位运算的种类分配

父亲的值知道,当且仅当在构造情况下两个儿子的值都知道

(我们针对位运算进行构造,与知道有0就是0,或知道有1就是1,要避免)

这时候知道父亲的时刻就是两个儿子中后知道值的那个的时刻

在顺序确定好后我们跑第二遍DFS

即可确定值

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define rii register int i
#define rij register int j
using namespace std;
int head[1000005],cnt,n;
struct edge{
    int cnt,bj,s[3],val,bh;
}x[1000005];
struct ljb{
    int to,nxt;
}y[4000005];
inline void add(int from,int to)
{
    cnt++;
    y[cnt].nxt=head[from];
    y[cnt].to=to;
    head[from]=cnt;
}
void ycl(int wz,int fa)
{
    for(rii=head[wz];i;i=y[i].nxt)
    {
        int to=y[i].to;
        if(to==fa)
        {
            continue;
        }
        x[wz].s[x[wz].cnt]=to;
        x[wz].cnt++;
        ycl(to,wz);
    }
    return;
}
void dfs(int wz)
{
    if(wz<=n)
    {
        return;
    }
    dfs(x[wz].s[1]);
    dfs(x[wz].s[0]);
    if(x[x[wz].s[0]].bh>x[x[wz].s[1]].bh)
    {
        swap(x[wz].s[0],x[wz].s[1]);
    }
    x[wz].bh=x[x[wz].s[1]].bh;
    return;
}
void dfs2(int wz)
{
    if(wz<=n)
    {
        return;
    }
    if(x[wz].bj==0)
    {
        if(x[wz].val==0)
        {
            x[x[wz].s[0]].val=1;
            x[x[wz].s[1]].val=0;
        }
        else
        {
            x[x[wz].s[0]].val=1;
            x[x[wz].s[1]].val=1;
        }
    }
    else 
    {
        if(x[wz].bj!=0)
        {
            if(x[wz].val==0)
            {
                x[x[wz].s[0]].val=0;
                x[x[wz].s[1]].val=0;
            }
               else
            {
                x[x[wz].s[0]].val=0;
                x[x[wz].s[1]].val=1;
            }
        }
    }
    dfs2(x[wz].s[0]);
    dfs2(x[wz].s[1]);
    return;
}
int main()
{
    scanf("%d",&n);
    for(rii=n+1;i<(n<<1);i++)
    {
        scanf("%d",&x[i].bj);
    }
    for(rii=1;i<=(n-1)<<1;i++)
    {
        int from,to;
        scanf("%d%d",&from,&to);
        add(from,to);
        add(to,from);
    }
    ycl(n+1,0);
    for(rii=1;i<=n;i++)
    {
        int from;
        scanf("%d",&from);
        x[from].bh=i;
    }
    dfs(n+1);
    x[n+1].val=1;
    dfs2(n+1);
    for(rii=1;i<=n;i++)
    {
        x[i].val?putchar(1):putchar(0);
    }
    return 0;
}

 

以上是关于code#5 P4 逻辑树的主要内容,如果未能解决你的问题,请参考以下文章

反向递归,树组件常用逻辑

反向递归,树组件常用逻辑

P4 开发实践 — 编程基础 — Controls 控制逻辑

P4 开发实践 — 编程基础 — Controls 控制逻辑

VS code自定义用户代码片段snippet

Sublime Text自定制代码片段(Code Snippets)