【NOIP2012模拟10.17】独立集

Description

对于一棵树,独立集是指两两互不相邻的节点构成的集合。例如,图1有5个不同的独立集(1个双点集合、3个单点集合、1个空集),图2有14个不同的独立集,图3有5536个不同的独立集。
在这里插入图片描述在这里插入图片描述【NOIP2012模拟10.17】独立集_第1张图片

Input

输入文件名为 duliji. in。

第一行一个正整数n,表示点的数量。n最大为100000。

接下来n-1行,有两个整数a、b,表示编号为a、b的两个点之间有一条边,其中a、b大于等于1,小于等于n。

Output

输出文件名为duliji.out。

输出一行,包含一个整数,表示独立集的数量。由于这个数很大,你只需要输出这个数除以10081的余数。

Sample Input
17
1 2
1 3
2 4
2 5
3 6
3 7
5 8
5 9
7 10
7 11
8 12
8 13
10 14
10 15
12 16
15 17

Sample Output
5536

.
.
.
.
.
分析
这是一道树形DP。
设f1[i]表示在选i个节点的独集数,f2[i]表示不选第i个节点的独集数。
很明显,每一个节点的f都是有它的子节点得到的。
如果选了第i个节点,那么它的子节点全部不选。所以,f1[i]就等于它的子节点f2[j]的乘积。
反之,不选第i个节点,那么它的子节点可以选也可以不选,f2[i]等于它的子节点(f1[j] +f2[j])的乘积。

.
.
.
.
.
.
程序:

#include
#include
#include
using namespace std;

struct edge
{
	int to,next;
}e[200010];

int mo=10081,f1[200010],f2[200010],cnt=0,head[200010];

void add(int x,int y)
{
	e[++cnt].to=y;e[cnt].next=head[x];head[x]=cnt;
	e[++cnt].to=x;e[cnt].next=head[y];head[y]=cnt;
}

void dp(int father,int x)
{
	f1[x]=f2[x]=1;
	for (int i=head[x];i;i=e[i].next)
	{
		if (e[i].to!=father)
		{
			dp(x,e[i].to);
			f1[x]=f2[e[i].to]*f1[x]%mo;
			f2[x]=(f1[e[i].to]+f2[e[i].to])*f2[x]%mo;
		}
	}
}

int main()
{
	int n;
	scanf("%d",&n);
	for (int i=1;i<=n-1;i++)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		add(x,y);
	}
	dp(-1,1);
	printf("%d",(f1[1]+f2[1])%mo);
}

你可能感兴趣的:(动态规划,c++,jzoj比赛,树)