[Jzoj] 3034.独立集

题目大意

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

题目解析

树形 D P DP DP
F [ i ] [ 1 ] F[i][1] F[i][1]表示以第 i i i个节点为根的子树并且选 i i i构成独立集的最多独立集数量。
F [ i ] [ 2 ] F[i][2] F[i][2]表示以第 i i i个节点为根的子树并且不选 i i i构成独立集的最多独立集数量。

对于每一个叶子节点,都将 F [ ] [ 1 ] = F [ ] [ 2 ] = 1 F[][1]=F[][2]=1 F[][1]=F[][2]=1
状态转移:
F [ i ] [ 1 ] = F [ i 的 所 有 子 节 点 ] [ 2 ] 的 乘 积 再 取 m o d F[i][1]=F[i的所有子节点][2]的乘积再取mod F[i][1]=F[i][2]mod
表示为选择当前节点 i i i,因为与子节点相邻,所以 i i i的所有子节点都不选。
F [ i ] [ 2 ] = ( F [ i 的 所 有 子 节 点 ] [ 1 ] + F [ i 的 所 有 子 节 点 ] [ 2 ] ) 的 乘 积 再 取 m o d F[i][2]=(F[i的所有子节点][1]+F[i的所有子节点][2])的乘积再取mod F[i][2]=(F[i][1]+F[i][2])mod
表示为不选择当前节点 i i i,因为与子节点无关了,所以把所有情况都相乘得出答案

最后 A n s = ( F [ 1 ] [ 1 ] + F [ 1 ] [ 2 ] ) Ans=(F[1][1]+F[1][2]) Ans=(F[1][1]+F[1][2]) m o d mod mod 10081 10081 10081

代码

#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;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值