zoukankan      html  css  js  c++  java
  • ARC121F

    ARC121F - Logical Operations on Tree

    题目大意

    给定一棵树,现在对于每一个点加上权值(a_iin{0,1}),每一条边加上操作(opt_iin{vee,wedge})

    每次操作选择一条边收缩两边的点,权值为两者操作的结果

    对于所有(2^{2n-1})种方案,求出所有 存在一种收缩顺序使得最终剩余的点权值为1的 方案数


    分析

    一开始我以为先做(vee),然后做(wedge),然后发现(1 - vee - 0 - wedge -0)就卡掉了

    仔细分析实际上是:

    如果一个0旁边有一个(wedge),那么这个0通过操作一定会把另一边的值赋为(0)

    为了浪费尽量少的1,这样的操作应该先做


    因此,贪心的策略是:

    1.先一直收缩到所有(wedge)旁边都是1

    2.然后任意顺序做

    所以实际上最优决策是先做(wedge)再做(vee)

    那么一个方案合法的判定:

    存在一个(wedge)边连成的联通块,其中所有数都是1

    const int N=1e5+10,P=998244353;
    
    int n;
    vector <int> G[N];
    int dp[N][2];
    void dfs(int u,int f){
    	dp[u][0]=dp[u][1]=1;
    	for(int v:G[u]) if(v!=f) {
    		dfs(v,u);
    		int t[2]={0,0};
    		rep(i,0,1) rep(j,0,1) t[i&j]=(t[i&j]+1ll*dp[u][i]*dp[v][j])%P;
    		rep(i,0,1) t[i]=(t[i]+1ll*dp[u][i]*dp[v][0])%P;
    		dp[u][0]=t[0],dp[u][1]=t[1];
    	}
    }
    
    int main(){
    	n=rd();
    	rep(i,2,n) {
    		int u=rd(),v=rd();
    		G[u].pb(v),G[v].pb(u);
    	}
    	dfs(1,0);
    	int ans=1;
    	rep(i,1,2*n-1) ans=ans*2%P;
    	printf("%d
    ",(ans-dp[1][0]+P)%P);
    }
    
  • 相关阅读:
    netty ByteToMessageDecoder 分析
    netty 编/解码处理
    MAC 入门
    netty 学习
    php ioc and web rest design
    spring 启动流程
    淘宝美衣人
    ecslipe cdt lib link
    阿里巴巴中间件团队招人了!
    架构师速成-架构目标之伸缩性安全性
  • 原文地址:https://www.cnblogs.com/chasedeath/p/14829004.html
Copyright © 2011-2022 走看看