一个点的改变如果对根节点的值不会造成任何影响,那么这个点的所有子节点的改变也不会对根节点造成影响
因为每次只改一个叶子节点,也就是一条到根的路径,可以先预处理出初始情况下的每个结点的值
分别讨论根节点是and,or,xor,not时,1|2 个结点取值 的 各种情况(也就那么几种)
比如x是and,x有两个儿子u,v,
u=1,v=1时改变任意一个都会有影响
u=0,v=1时改变u会有影响
u=1,v=0时改变v会有影响
依次类推其他操作
/* 给定一棵逻辑运算的树,非叶子结点有and,or,xor,not四种操作 每个叶子结点都是一个输入 问每个叶子结点求反后可以得到的结果 先一次dfs求出每个结点的值 and:1 or:2 xor:3 not:4 */ #include<bits/stdc++.h> #include<vector> using namespace std; #define maxn 1000006 vector<int>G[maxn]; int n,a[maxn],op[maxn],flag[maxn]; void dfs1(int u){ if(op[u]==0)return; for(int i=0;i<G[u].size();i++) dfs1(G[u][i]); if(op[u]==1) a[u]=a[G[u][0]] & a[G[u][1]]; if(op[u]==2) a[u]=a[G[u][0]] | a[G[u][1]]; if(op[u]==3) a[u]=a[G[u][0]] ^ a[G[u][1]]; if(op[u]==4) a[u]=!a[G[u][0]]; } //flag[i]=1表示结点i的改变会改变根节点 void dfs2(int u,int f){ if(op[u]==0)return; if(f==0){//下面任意一个结点改变都没影响了 for(int i=0;i<G[u].size();i++){ flag[G[u][i]]=0; dfs2(G[u][i],0); } return; } int x,y; if(op[u]==1){//and x=G[u][0],y=G[u][1]; if(a[x] && a[y]){ flag[x]=flag[y]=1; dfs2(x,1);dfs2(y,1); } else if(a[x] && !a[y]){ flag[y]=1; dfs2(x,0);dfs2(y,1); } else if(!a[x] && a[y]){ flag[x]=1; dfs2(x,1);dfs2(y,0); } else dfs2(x,0),dfs2(y,0); } if(op[u]==2){ x=G[u][0],y=G[u][1]; if(!a[x] && !a[y]){ flag[x]=flag[y]=1; dfs2(x,1);dfs2(y,1); } else if(a[x] && !a[y]){ flag[x]=1; dfs2(x,1);dfs2(y,0); } else if(!a[x] && a[y]){ flag[y]=1; dfs2(x,0);dfs2(y,1); } else dfs2(x,0),dfs2(y,0); } if(op[u]==3){ x=G[u][0],y=G[u][1]; flag[x]=flag[y]=1; dfs2(x,1);dfs2(y,1); } if(op[u]==4){ flag[G[u][0]]=1; dfs2(G[u][0],1); } } int main(){ cin>>n; for(int i=1;i<=n;i++){ char s[5]; int aa,b; scanf("%s",s); if(s[0]=='A'){ scanf("%d%d",&aa,&b); G[i].push_back(aa); G[i].push_back(b); op[i]=1; } if(s[0]=='O'){ scanf("%d%d",&aa,&b); G[i].push_back(aa); G[i].push_back(b); op[i]=2; } if(s[0]=='I') scanf("%d",&a[i]); if(s[0]=='X'){ scanf("%d%d",&aa,&b); G[i].push_back(aa); G[i].push_back(b); op[i]=3; } if(s[0]=='N'){ scanf("%d",&aa); G[i].push_back(aa); op[i]=4; } } dfs1(1);//第一次dfs求出每个结点的初始值 int ans=a[1]; dfs2(1,1); for(int i=1;i<=n;i++) if(op[i]==0){ if(flag[i])cout<<!ans; else cout<<ans; } }