题目大意
对于一棵树,独立集是指两两互不相邻的节点构成的集合。例如,图111有555个不同的独立集(111个双点集合、333个单点集合、111个空集),图222有141414个不同的独立集,图333有553655365536个不同的独立集。
题目解析
树形DPDPDP
设F[i][1]F[i][1]F[i][1]表示以第iii个节点为根的子树并且选iii构成独立集的最多独立集数量。
F[i][2]F[i][2]F[i][2]表示以第iii个节点为根的子树并且不选iii构成独立集的最多独立集数量。
对于每一个叶子节点,都将F[][1]=F[][2]=1F[][1]=F[][2]=1F[][1]=F[][2]=1。
状态转移:
F[i][1]=F[i的所有子节点][2]的乘积再取modF[i][1]=F[i的所有子节点][2]的乘积再取modF[i][1]=F[i的所有子节点][2]的乘积再取mod
表示为选择当前节点iii,因为与子节点相邻,所以iii的所有子节点都不选。
F[i][2]=(F[i的所有子节点][1]+F[i的所有子节点][2])的乘积再取modF[i][2]=(F[i的所有子节点][1]+F[i的所有子节点][2])的乘积再取modF[i][2]=(F[i的所有子节点][1]+F[i的所有子节点][2])的乘积再取mod
表示为不选择当前节点iii,因为与子节点无关了,所以把所有情况都相乘得出答案
最后Ans=(F[1][1]+F[1][2])Ans=(F[1][1]+F[1][2])Ans=(F[1][1]+F[1][2]) modmodmod 100811008110081
代码
#include<bits/stdc++.h>
#define N 100005
#define M 10081
using namespace std;
int n,cnt;
int v[N*2],next[N*2],last[N*2];
long long f[N][3];
bool flag[N];
void ins(int x,int y)
{
cnt++;
v[cnt]=y;
next[cnt]=last[x];
last[x]=cnt;
}
void dfs(int x)
{
int f1=1,f2=1,k;
flag[x]=1;
k=last[x];
while(k!=0)
{
if(!flag[v[k]])
{
dfs(v[k]);
f1=(f1*f[v[k]][2])%M;
f2=(f2*(f[v[k]][1]+f[v[k]][2]))%M;
}
k=next[k];
}
f[x][1]=f1;
f[x][2]=f2;
}
int main()
{
cin>>n;
int x,y;
for(int i=1;i<n;i++)
{
cin>>x>>y;
ins(x,y);ins(y,x);
}
dfs(1);
cout<<(f[1][1]+f[1][2])%M;
}