树形dp——cf1332F【好题】

思维题

/*
题意:给定一棵树,规定一种染色方案,要求有边相邻结点不能同时染色
    求所有边诱导子图的染色方案数之和
转化:只有两个条件:1.右边相邻的结点不能同时染色
                    2.染色点至少要有一条边
f[u][0|1]表示不管u到父亲有没有边,该点不染色|染色,子树u的方案数
g[u]表示u和所有儿子之间没有边相连的方案数 

f[u][0]=mul{ 2*f[v][0]+2*f[v][1]-g[v] } 
    u不染色,v不染色时,(u,v)可有可无
    u不染色,v染色时,那么v至少要有一条边连着,当(u,v)没有时,要减去g[v]
f[u][1]=mul{ 2*f[v][0]+f[v][1]-g[v] }
    u染色,v不染色时,(u,v)可由可无
    u染色,v染色时,(u,v)不可存在,且要减去g[v]的情况             
g[u]=mul{ f[v][0]+f[v][1]-g[v] }
    (u,v)不存在,v可染色也可以不染色,但是染色的话要减去v和所有儿子无边的情况 
*/
#include<bits/stdc++.h>
using namespace std;
#define ll long long 
#define mod 998244353
#define N 500005

vector<int>G[N];
int n;
ll f[N][2],g[N]; 

void dfs(int u,int pre){
    for(auto v:G[u])
        if(v!=pre)dfs(v,u);
    f[u][0]=f[u][1]=g[u]=1;
    for(auto v:G[u])
        if(v!=pre){
            f[u][0]=(2*f[v][0]%mod+2*f[v][1]%mod-g[v]+2*mod)%mod*f[u][0]%mod;
            f[u][1]=(2*f[v][0]%mod+f[v][1]-g[v]+2*mod)%mod*f[u][1]%mod;
            g[u]=(f[v][0]+f[v][1]-g[v]+2*mod)%mod*g[u]%mod;
        } 
}

int main(){
    cin>>n;
    for(int i=1;i<n;i++){
        int u,v;cin>>u>>v;
        G[u].push_back(v);
        G[v].push_back(u);
    }
    dfs(1,1);
    
    //root不染色+root染色且和下面有边相连-都不染色 
    cout<<(f[1][0]+f[1][1]-g[1]-1+2*mod)%mod<<'\n';
} 

猜你喜欢

转载自www.cnblogs.com/zsben991126/p/12633927.html