牛牛染顏色---------------------------------樹形dp

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
解析:

設f[u][0/1] 表示不選擇u和選擇u 以u爲根的子樹的方案數

討論一:
我們選擇u節點,那麼以u爲根的子樹內的節點隨便取。因爲不管你怎麼取 lca(x,y)=u 都是符合題意的 狀態方程就是
在這裏插入圖片描述
討論二:
我們不選擇u節點,那麼只能選擇一棵子樹內的節點或者都不選。因爲如果在以u爲根的子樹內選兩點 會出現lca(x,y)=u 的情況,不滿足題意。

又因爲每個不選擇u節點的,會多一個空集。因爲最多只能有一個空集,所以以u爲根的子樹對答案的貢獻-1. 最後加上空集的貢獻
狀態方程
在這裏插入圖片描述

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+1000;
const int MOD=1e9+7;
ll f[N][2];
int n,h[N*2],e[N*2],ne[N*2],idx,a,b,t;
void add(int a,int b)
{
	e[idx]=b;ne[idx]=h[a];h[a]=idx++;
}
void dfs(int u,int fa)
{
	f[u][1]=1;f[u][0]=1;//包含空集
	for(int i=h[u];~i;i=ne[i])
	{
		int v=e[i];
		if(v==fa) continue;
		dfs(v,u);
		f[u][1]=(f[u][1]*(f[v][0]+f[v][1]))%MOD;
		f[u][0]=(f[u][0]+f[v][1]+f[v][0]-1)%MOD;
	 } 
}
int main()
{
	memset(h,-1,sizeof h);
	scanf("%d",&t);
	t=t-1;
	while(t--)
	{
		scanf("%d %d",&a,&b);
		add(a,b);add(b,a);
	}
	dfs(1,0);
	cout<<(f[1][0]+f[1][1])%MOD<<endl;
 } 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章