树上染色(树形dp)

第2题     树上染色 查看测评数据信息

有一个n个节点的树,每个节点染色成黑色或白色,要求任意相邻的节点不能都是黑色,问一共有多少种染色方案,答案对1000000007取模。

输入格式

 

第一行一个整数n

接下来n-1行,每行两个整数u,v,表示u到v有一条边。

1<=n<=1e5,1<=u,v<=n

 

输出格式

 

一个整数

 

输入/输出例子1

输入:

3

1 2

2 3

 

输出:

5

 

输入/输出例子2

输入:

4

1 2

1 3

1 4

 

输出:

9

 

样例解释

 

 

求方案数时注意分清楚加法原理和乘法原理!!!最好推算一下

还是比较简单,但是我考场上没切出来!!!!!!可恶了。

这题一看就是树形dp,而不是换根。

考虑记  f[i][0/1],表示以i为子树,i节点染(0黑1白)时染色方案总数

 

注意一下,因为这里是求方案总数,肯定是乘法原理

理解一下:假设u的第一个子树v1,选了1个点,那么u的第二个子树v2,可以选cnt[v2]个点,然后v1可以选2个点,v2继续选cnt[v2]

也就是两棵子树的选择方法不单单相加,他俩有一处不同即可,也就是乘法原理

考场上就是这里出错了!

 

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+5, Mod=1000000007;

int n, u1, v1, root=0, rd[N];
vector<int> a[N];
long long f[N][5];
void dfs(int u, int fa)
{
	f[u][0]=f[u][1]=1;
	for (int i=0; i<a[u].size(); i++)
	{
		int v=a[u][i];
		if (v==fa) continue;
		
		dfs(v, u);
		f[u][0]=(f[u][0]*f[v][1])%Mod;
		f[u][1]=(f[u][1]*(f[v][1]+f[v][0]))%Mod;
	}
}
int main()
{
	scanf("%d", &n);
	for (int i=1; i<n; i++)
	{
		scanf("%d%d", &u1, &v1);
		a[u1].push_back(v1);
		a[v1].push_back(u1);
		
		rd[v1]++;
	}
	for (int i=1; i<=n; i++)
		if (!rd[i])
		{
			root=i;
			break;
		}
	dfs(root, -1);
	
	printf("%lld", (f[root][0]+f[root][1])%Mod);
	return 0; 
} 

  

 

 

 

 

 

posted @ 2024-08-23 07:34  cn是大帅哥886  阅读(35)  评论(0)    收藏  举报