NEUOj 涂色
没找到ATC里面对应哪个题。
就把题直接粘贴过来了
Problem Statement
有一棵有N个节点的树,节点编号为1,2,…,N,对每个i (1≤i≤N−1),第i条边连着x**i和y**i节点。
Taro 决定将每个节点都涂成黑色或者白色,不能将两个相邻的节点同时涂黑。
找到他能涂色的方案数并对1e9+7取模。
Constraints
- 所有输入均为整数
- 1≤N≤1e5
- 1≤x**i,y**i≤N
- 所给图是一棵树
Input
N
x1 y1
.
.
xN yN
Output
输出他能涂色的方案数并对1e9+7取模。
输入样例
4
1 2
1 3
1 4
输出样例
9
提示:
有9种方法涂色:
用树上dp,white[i] 表示i位置取白色时的方案数,black[i]表示i位置取黑色时的方案数。
那么叶子节点均取1。对于一个中间节点i,对于white[i]来说是每个子树的black[k]+white[k] 相乘, 对于black[i]是white[k]相乘。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
const int N = 1e5 + 100;
const int mod = 1e9 + 7;
typedef long long ll;
vector<int> G[N];
ll black[N], white[N];
void dfs(int cur, int fa) {
if (G[cur].size() == 1 && fa != -1) {
black[cur] = 1;
white[cur] = 1;
return;
}
ll tem1 = 1, tem2 = 1;
for (int i = 0; i < G[cur].size(); i++) {
int nx = G[cur][i];
if (fa == nx) continue;
dfs(nx, cur);
tem1 *= (black[nx] + white[nx]);
tem2 *= white[nx];
tem1 %= mod;
tem2 %= mod;
}
black[cur] += tem2;
black[cur] %= mod;
white[cur] += tem1;
white[cur] %= mod;
}
int main() {
int n;
cin >> n;
for (int i = 1; i < n; i++) {
int a, b;
cin >> a >> b;
G[a].push_back(b);
G[b].push_back(a);
}
dfs(1, -1);
cout << (black[1] + white[1]) % mod << endl;
}