0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AtCoder Educational DP Contest P問題解いてみた

Posted at

AtCoder Educational DP Contest P問題解いてみた

今回の問題

問題文

$N$ 頂点の木があります。 頂点には $1, 2, \ldots, N$ と番号が振られています。
各 $i$ ($1 \leq i \leq N-1$) について、$i$ 番目の辺は頂点 $x_i$ と $y_i$ を結んでいます。

太郎君は、各頂点を白または黒で塗ることにしました。
ただし、隣り合う頂点どうしをともに黒で塗ってはいけません。

頂点の色の組合せは何通りでしょうか?
$10^9 + 7$ で割った余りを求めてください。

制約

  • 入力はすべて整数である。
  • $1 \leq N \leq 10^5$
  • $1 \leq x_i, y_i \leq N$
  • 与えられるグラフは木である。

自分の回答

#include <bits/stdc++.h>
using namespace std;

const int MOD = 1e9 + 7;


vector<vector<int>> adj;

long long dp[100005][2];


void dfs(int u, int p) {
    
    dp[u][0] = 1;
    dp[u][1] = 1;

    for (int v : adj[u]) {
        if (v == p) continue; 
        dfs(v, u);

        
        long long ways_white = (dp[v][0] + dp[v][1]) % MOD;
        dp[u][0] = (dp[u][0] * ways_white) % MOD;
        long long ways_black = dp[v][0];
        dp[u][1] = (dp[u][1] * ways_black) % MOD;
    }
}

int main() {
    int N;
    cin >> N;
    adj.resize(N + 1);
    
    for (int i = 0; i < N - 1; i++) {
        int u, v;
        cin >> u >> v;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }

    dfs(1, -1);

    long long ans = (dp[1][0] + dp[1][1]) % MOD;
    
    cout << ans << endl;

    return 0;
}

自分なりの解説

木であることより、メモ化再起で解くことを考えた。dp[i][color]をiをcolorで塗った時のその部分木の場合の数とする。黒と黒は隣接しないように注意するととくことができる。初見で解くことができた。最初葉を探そうとしたが探さなくてもよいことに気が付いた。また、場合の数になるので、足し算でなく掛け算しないといけないことにも注意が必要である。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?