予鈴

競プロとか備忘録とか…

D-塗り絵

 
D: 塗り絵 - AtCoder Beginner Contest 036 | AtCoder

N個の島があり、N-1個の橋がある。
島を白または黒に塗っていく。ただし、両端の島を黒で塗ることはできない。
色の塗り方が何通りあるか求める問題です。

グラフ上の頂点を、黒色で塗るか、白色で塗るかをメモ化再帰で求めていきます。

memo[v][color]:=頂点vを  colorで塗ったときの場合の数

とします。(1が白、0が黒)


(1)頂点vを白色に塗るとき(uvの子の数)

vの子は白、黒の2つの色に塗ることができるので
memo[v][1] =( memo[nv_1][1]+ memo[nv_1][0])*\cdots*( memo[nv_u][1]+ memo[nv_u][0])


(2)頂点vを黒色に塗るとき

vの子は白色に塗ることができるので
memo[v][0] = ( memo[nv_1][1])*\cdots*( memo[nv_u][1]


ただし、 vが葉となる場合は1とします。

#include<bits/stdc++.h>
#define vi vector<int>
#define vvi vector<vector<int> >
#define vl vector<ll>
#define vvl vector<vector<ll>>
#define vb vector<bool>
#define vc vector<char>
#define vs vector<string>
using ll = long long;
using ld =long double;
#define int ll
#define INF 1e9
#define EPS 0.0000000001
#define rep(i,n) for(int i=0;i<n;i++)
#define loop(i,s,n) for(int i=s;i<n;i++)
#define all(in) in.begin(), in.end()
template<class T, class S> void cmin(T &a, const S &b) { if (a > b)a = b; }
template<class T, class S> void cmax(T &a, const S &b) { if (a < b)a = b; }
#define MAX 9999999
using namespace std;
typedef pair<int, int> pii;
typedef pair<int,pii> piii;
#define mp make_pair
int MOD = INF+7;
int memo[100005][2];
vector<vector<int>>edge;

int dfs(int v,int from,int clr){
    if(memo[v][clr]!=INF)return memo[v][clr];
    memo[v][clr]=0;
    bool leaf =  true;
    int value=1;
    rep(i,edge[v].size()){
        int nv=edge[v][i];
        if(nv == from)continue;
        leaf = false;
        if(clr){
            value*=(dfs(nv,v,0)+dfs(nv,v,1));
            value%= MOD;
        }else{
            value*=dfs(nv,v,1);
            value%=(MOD);
        }
    }
    if(leaf)memo[v][clr]=1;
    else memo[v][clr]=value;
    return memo[v][clr];
}
signed main(){
    int n;
    cin>>n;
    edge.resize(n);
    rep(i,n-1){
        int a,b; cin>>a>>b;
        --a,--b;
        edge[a].push_back(b);
        edge[b].push_back(a);
    }
    rep(i,n)rep(j,2)memo[i][j]=INF;
    cout<<(dfs(0,0,1)+dfs(0,0,0))%(MOD)<<endl;
    
}