zoukankan      html  css  js  c++  java
  • 树形dp——cf1010D

    一个点的改变如果对根节点的值不会造成任何影响,那么这个点的所有子节点的改变也不会对根节点造成影响

    因为每次只改一个叶子节点,也就是一条到根的路径,可以先预处理出初始情况下的每个结点的值

    分别讨论根节点是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;
            }
    }
  • 相关阅读:
    NGINX基本概念
    IP地址进制转换
    路由
    ip ,网段, 网关
    ipaddress模块
    第53课 被遗弃的多重继承(上)
    const static valitate 区别
    第49课 多态的概念和意义 (虚函数virtual)
    第75课 图的遍历(深度优先遍历DFS)
    第74课 图的遍历(广度优先遍历BFS)
  • 原文地址:https://www.cnblogs.com/zsben991126/p/10955785.html
Copyright © 2011-2022 走看看