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;
            }
    }
  • 相关阅读:
    洛谷 P1194 飞扬的小鸟 题解
    洛谷 P1197 星球大战 题解
    洛谷 P1879 玉米田Corn Fields 题解
    洛谷 P2796 Facer的程序 题解
    洛谷 P2398 GCD SUM 题解
    洛谷 P2051 中国象棋 题解
    洛谷 P1472 奶牛家谱 Cow Pedigrees 题解
    洛谷 P1004 方格取数 题解
    洛谷 P2331 最大子矩阵 题解
    洛谷 P1073 最优贸易 题解
  • 原文地址:https://www.cnblogs.com/zsben991126/p/10955785.html
Copyright © 2011-2022 走看看