题意:
有一棵逻辑运算树,叶子节点为输入节点(IN),取值0/1;其他节点有AND/OR/XOR/NOT四种类型,并根据儿子节点取不同的值。输出为根节点的值。
初始每个输入节点的值给定(因此所有节点的值确定)。问单独改变每个输入节点的值而保持其他输入节点不变,输出是多少
思路:
二叉树,每个节点存储节点类型(IN/ANS/OR/XOR/NOT)、节点值、左儿子、右儿子。
dfs1从下往上算出初始所有节点的值。dfs2从上往下,看某个节点的值是否会被儿子影响,若会被某个儿子影响就搜索这个儿子,否则不往下传导。最终得到每个叶子节点能否影响根节点。
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5;
struct node {
int lson, rson;
char ty; int val;
} tr[N];
int dfs1(int u)
{
if(!u) return 0;
int lv = dfs1(tr[u].lson), rv = dfs1(tr[u].rson);
if(tr[u].ty == 'I') return tr[u].val;
if(tr[u].ty == 'N') return tr[u].val = !lv;
if(tr[u].ty == 'A') return tr[u].val = lv & rv;
if(tr[u].ty == 'O') return tr[u].val = lv | rv;
if(tr[u].ty == 'X') return tr[u].val = lv ^ rv;
}
int change[N]; //只记录叶子节点的change值
void dfs2(int u)
{
if(tr[u].ty == 'I') change[u] = 1;
else if(tr[u].ty == 'N') dfs2(tr[u].lson);
else if(tr[u].ty == 'A') {
if(tr[tr[u].lson].val && !tr[tr[u].rson].val) dfs2(tr[u].rson);
else if(!tr[tr[u].lson].val && tr[tr[u].rson].val) dfs2(tr[u].lson);
else if(tr[tr[u].lson].val && tr[tr[u].rson].val)
dfs2(tr[u].lson), dfs2(tr[u].rson);
}
else if(tr[u].ty == 'O') {
if(tr[tr[u].lson].val && !tr[tr[u].rson].val) dfs2(tr[u].lson);
else if(!tr[tr[u].lson].val && tr[tr[u].rson].val) dfs2(tr[u].rson);
else if(!tr[tr[u].lson].val && !tr[tr[u].rson].val)
dfs2(tr[u].lson), dfs2(tr[u].rson);
}
else if(tr[u].ty == 'X') dfs2(tr[u].lson), dfs2(tr[u].rson);
}
signed main()
{
int n; scanf("%d", &n); char op[6];
for(int i = 1; i <= n; i++) {
scanf("%s", op); tr[i].ty = op[0];
if(op[0] == 'I') scanf("%d", &tr[i].val);
else if(op[0] == 'N') scanf("%d", &tr[i].lson);
else scanf("%d%d", &tr[i].lson, &tr[i].rson);
}
dfs1(1), dfs2(1);
int t = tr[1].val;
for(int i = 1; i <= n; i++) if(!tr[i].lson) {
printf("%d", change[i] ^ t);
}
return 0;
}