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);
}