The 15th Chinese Northeast Collegiate Programming Contest D - Vertex Deletion (树形dp)
时间:2021-09-04
本文章向大家介绍The 15th Chinese Northeast Collegiate Programming Contest D - Vertex Deletion (树形dp),主要包括The 15th Chinese Northeast Collegiate Programming Contest D - Vertex Deletion (树形dp)使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
题意:
给定一个由\(n\)个点组成的树,然后每次可以从树中选择一个顶点删去,定义操作结束后是完美的,但且仅当删点后形成的点集中,每个点都有至少一个点与它相连,问一共有多少种删点方式能够形成完美的局面,答案模\(998244353\)。
思路:
统计方案类的问题,可以往\(dp\)方向靠,又是在树上,那么就是树形\(dp\)了。
题目要求都必须有节点相连才是合法转态且又是否删除这个操作选项,那就考虑状态预设的时候要带上节点连接子节点情况的信息和是否删除的信息,即可用三个状态来囊括。
考虑令
\(dp_{u,0}\)表示当前点删除后能形成的方案数。
\(dp_{u,1}\)表示当前点保留且至少有一个子节点与它相连形成的方案数。
\(dp_{u,2}\)表示当前点保留且没有任何一个子节与它相连的方案数
按照如下方式转移即可。
特别注意第三种转移,会计算到当前点的所有儿子都取删除的这一种情况,不符合题意,应当删去这种情况,至少留有一个子节点,不确定留那个,只能这样用\(size(u)\)个和式相乘转移,乘起来拆开后之后就会是一些包含\(dp[v][0]\)存在\([0,size(u)]\)次的式子,很明我们只需要把存在\(size(u)\)的答案删去即为至少存在一个子节点的答案。
从节点\(1\)开始遍历,可知最终答案即为\(dp[1][0]+dp[1][1]\)
#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define eb emplace_back
#define MP make_pair
#define pii pair<int,int>
#define pll pair<ll,ll>
#define lson rt<<1
#define rson rt<<1|1
#define CLOSE std::ios::sync_with_stdio(false)
#define sz(x) (int)(x).size()
typedef long long ll;
typedef double db;
const int INF = 0x3f3f3f3f;
const db eps = 1e-6;
const int N = 1e5 + 10;
const ll MOD = 998244353;
int n,siz[N];
std::vector<int>G[N];
ll f[N][3];
//0/1/2记录当前u点的三种状态 0代表删除 1代表保留且该点至少与一个子节点相连 2代表保留且不与任意一个子节点相连
void dfs(int u,int fa) {
f[u][0] = f[u][1] = f[u][2] = 1;
for(auto v : G[u]) {
if(v == fa) continue;
dfs(v,u);
f[u][0] = f[u][0] * (f[v][0] + f[v][1]) % MOD;
f[u][2] = f[u][2] * f[v][0] % MOD;
f[u][1] = f[u][1] * (f[v][0] + f[v][1] + f[v][2]) % MOD;
}
//此时f[u][1]会包含着一种 所有点都不与之相连的状态 所以需要去掉这个状态
f[u][1] = (f[u][1] - f[u][2] + MOD) % MOD;
}
void solve() {
scanf("%d",&n);
for(int i = 1;i <= n;i ++) G[i].clear();
for(int i = 1,u,v;i < n;i ++) {
scanf("%d%d",&u,&v);
G[u].pb(v),G[v].pb(u);
}
dfs(1,-1);
ll ans = (f[1][0] + f[1][1]) % MOD;
printf("%lld\n",ans);
}
int main() {
int T;scanf("%d",&T);
while(T--) solve();
return 0;
}
原文地址:https://www.cnblogs.com/forward77/p/15227695.html
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 基于Apriori的数据关联分析 | 工业数据分析 | 冰水数据智能专题 | 4th
- 基于FP树的频繁项挖掘 | 工业数据分析 | 冰水数据智能 | 5th
- ICCV2019 高通Data-Free Quantization论文解读
- VBA解压缩ZIP文件10——解压-动态Huffman
- 海思NNIE之PFPLD训练与量化
- [译] 用 Truffle 插件自动在Etherscan上验证合约代码
- 二层网络上的以太坊智能合约: Optimistic Rollup
- 基于决策树的工业数据分类——数据智能
- Kestrel的ListenAnyIP和ListenLocalhost的区别
- 【为宏正名】什么?我忘了去上“数学必修课”!
- 第6章 Jenkins系统权限划分与授权管理
- Python爬虫新手教程: 知乎文章图片爬取器
- 《重构-代码整洁之道TypeScript版》第4天
- C++基础 杂记(一)
- 一种Cortex-M内核中的精确延时方法(ns级别)