【NOIP2012模拟10.17】独立集

Description

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

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<iostream>
#include<cstdio>
#include<cstring>
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);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值