[Jzoj] 3034.独立集

题目大意

对于一棵树,独立集是指两两互不相邻的节点构成的集合。例如,图111555个不同的独立集(111个双点集合、333个单点集合、111个空集),图222141414个不同的独立集,图333553655365536个不同的独立集。
在这里插入图片描述

题目解析

树形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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值