当前位置: 首页 > news >正文

CF 461 B Appleman and Tree 题解(树形 dp+排列组合)

原题传送门

思路

求方案数,肯定是排列组合,dp 一类的,猜测此题为树形 dp。先写出 d p i dp_i dpi,发现无法决定是否截断,得要看连通块里有没有黑色的节点,变成两维 d p i , 0 / 1 dp_{i,0/1} dpi,0/1 就可以判断了。(本人很懒,所以直接祭出自己的笔记本,字丑见谅)
在这里插入图片描述
在这里插入图片描述

代码

注意:

  1. 要取模,写乘法逆元。
  2. 节点编号从零开始,建议集体加一。集体加一的情况下,输入的 p 0 p_0 p0 加上 1 表示 2 连到的节点。
  3. 边界条件是 go[ps].size()<=1&&fa!=0,因为如果是根节点,只有一条边连出去表示只有一个儿子而不是没有儿子。
#include<bits/stdc++.h>
using namespace std;
#define mod 1000000007
int n,x,c[100005];
long long dp[100005][2];
vector<int> go[100005];
long long mi(long long x,int y){if(y==1) return x;long long t=mi(x,y/2);return t*t%mod*(y%2?x:1)%mod;
}
void dfs(int ps,int fa){if(go[ps].size()<=1&&fa!=0){dp[ps][c[ps]]=1;return;}for(auto j:go[ps]) if(j!=fa) dfs(j,ps);int i=ps;if(c[ps]){dp[i][1]=1;for(auto j:go[ps]) if(j!=fa)dp[i][1]=dp[i][1]*((dp[j][0]+dp[j][1])%mod)%mod;}else{dp[i][0]=1;for(auto j:go[ps]) if(j!=fa)dp[i][0]=dp[i][0]*((dp[j][0]+dp[j][1])%mod)%mod;for(auto j:go[ps]) if(j!=fa)dp[i][1]=(dp[i][1]+dp[i][0]*dp[j][1]%mod*mi(dp[j][0]+dp[j][1],mod-2)%mod)%mod;}
}
int main(){cin>>n;for(int i=2;i<=n;i++){cin>>x;x++;go[i].push_back(x);go[x].push_back(i);}for(int i=1;i<=n;i++) cin>>c[i];dfs(1,0);cout<<dp[1][1]<<endl;return 0;
}

http://www.mrgr.cn/news/34556.html

相关文章:

  • MySQL和SQL的区别简单了解和分析使用以及个人总结
  • 手写数字识别案例分析(torch,深度学习入门)
  • 看Threejs好玩示例,学习创新与技术(React-three-fiber)
  • 有空格输入
  • Java设计模式——工厂模式扩展
  • Vue3(二)计算属性Computed,监视属性watch,watchEffect,标签的ref属性,propos属性,生命周期,自定义hook
  • gtk安装和测试
  • 半导体芯闻--20240923
  • Vue使用Vue Router路由:通过URL传递与获取参数
  • excel怎么转换json
  • Java刷题知识总结(一)
  • mapty项目架构
  • 【链表操作】前驱和后继
  • 个人防护装备检测系统源码分享
  • 全栈开发(一):springBoot3+mysql初始化
  • LPDDR4芯片学习(一)——基础知识与引脚定义
  • 初始docker以及docker的基本使用!!!
  • 苍穹外卖上半部分总结
  • 【灭鼠先锋 / B】
  • 《CUDA编程》1.GPU硬件与CUDA环境搭建