NC19782 Tree
题目
题目描述
修修去年种下了一棵树,现在它已经有n个结点了。
修修非常擅长数数,他很快就数出了包含每个点的连通点集的数量。
澜澜也想知道答案,但他不会数数,于是他把问题交给了你。
输入描述
第一行一个整数 \(n (1≤ n ≤ 10^6)\) ,接下来n-1行每行两个整数 \(a_i,b_i\) 表示一条边 \((1≤ a_i,b_i≤ n)\) 。
输出描述
输出n行,每行一个非负整数。第i行表示包含第i个点的连通点集的数量对 \(10^9+7\) 取模的结果。
示例1
输入
6
1 2
1 3
2 4
4 5
4 6
输出
12
15
7
16
9
9
题解
知识点:树形dp,计数dp。
一道树形dp,注意到要求每个点的贡献,因此需要二次扫描+换根。
第一次先随便选个点,这里考虑以 \(1\) 为根开始dp。设 \(dp[u]\) 表示 \(u\) 为根的子树中过 \(u\) 的连通点集数量,转移方程为:
\]
表示合并以子节点 \(v\) 为根的子树的方案数,加一是不选 \(v\) 这个子树的一种可能,乘法原理合并。
第二次,在得到了各个子树答案后,可以顺推完整答案。设 \(f[u]\) 表示过 \(u\) 的连通点集数量,转移方程为:
\]
表示从父节点的答案 \(ans[u]\) 删去选或不选 \(v\) 这一支路选的答案 \(dp[v]+1\) ,再加上不选父节点 \(u\) 的答案一种,与 \(v\) 支路的答案进行乘法原理合并,最终得到 \(v\) 的完整答案 \(ans[v]\) ,其中需要求 \(dp[v]+1\) 的逆元。
但有个大坑,\(dp[v]+1 \equiv 0 \quad (\mod 10^9+7)\) 时是没有逆元的,这时候只能重新求一遍 \(\frac{ans[u]}{dp[v]+1}\) 。
如果重新开始求,把 \(u\) 作为根节点再求一次 \(dp[u]\) ,这样复杂可能会退化到枚举根的程度。
因此,考虑设 \(f[v] = \frac{ans[u]}{dp[v]+1}\) ,于是 \(ans[v] = dp[v] \cdot (f[v]+1)\) ,\(f[v]\) 可以在每次求 \(ans[v]\) 前先求出。如果 \(dp[v]+1\) 有逆元 \((dp[v]+1)^{-1}\) ,则 \(f[v] = ans[u] \cdot (dp[v]+1)^{-1}\) ;如果没有,则 \(f[v] = \frac{ans[u]}{dp[v]+1} = \frac{dp[u] }{dp[v]+1} \cdot (f[u]+1)\) ,其中 $ \dfrac{dp[u] }{dp[v]+1}$ 只需要求一遍 \(\prod (dp[v_i]+1),v_i \not= v\) 。注意初始时 \(f[1] = 0\) ,因为此时 \(ans[1] = dp[1]\) 。
时间复杂度 \(O(n)\)
空间复杂度 \(O(n)\)
代码
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int mod = 1e9 + 7;
struct Graph {
int n;
struct edge {
int to, nxt;
};
vector<edge> e;
vector<int> h;
explicit Graph(int _n) :n(_n), h(_n + 1, -1) {}
void add(int u, int v) {///加边
e.push_back(edge{ v,h[u] });///边结束节点,边出发节点的上一条边在e中下标,边权
h[u] = e.size() - 1;///上一条边的下标
}
};
Graph g(1000007);
ll dp[1000007], f[1000007];
ll qpow(ll a, ll k) {
ll ans = 1;
while (k) {
if (k & 1) ans = ans * a % mod;
k >>= 1;
a = a * a % mod;
}
return ans;
}///求逆元,但得到0时代表没有逆元,因此要重新求
void dfs1(int u, int fa) {
dp[u] = 1;
for (int i = g.h[u];~i;i = g.e[i].nxt) {
int v = g.e[i].to;
if (v == fa) continue;
dfs1(v, u);
dp[u] = dp[u] * (dp[v] + 1) % mod;
}
}///处理出子树中过根节点的答案dp[u]
void dfs2(int u, int fa) {
for (int i = g.h[u];~i;i = g.e[i].nxt) {
int v = g.e[i].to;
if (v == fa) continue;
int inv = qpow(dp[v] + 1, mod - 2);
if (inv) f[v] = dp[v] * (f[u] * inv % mod + 1) % mod;///inv可以用
else {
int tmp = 1;
for (int j = g.h[u];~j;j = g.e[j].nxt) {
int vt = g.e[j].to;
if (vt == fa || vt == v) continue;
tmp = tmp * (dp[vt] + 1) % mod;
}
f[v] = dp[v] * (tmp + 1) % mod;
}///不能用就重新算一下f[u]/(dp[v]+1)
dfs2(v, u);
}
}///通过上一次处理的答案dp[u],求出完整答案f[v] = dp[v] * (f[u]/(dp[v]+1) + 1)
///表示自己子树的答案与父节点除了自己的答案加上不选父节点的答案相互匹配
int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n;
cin >> n;
for (int i = 1;i < n;i++) {
int u, v;
cin >> u >> v;
g.add(u, v);
g.add(v, u);
}
dfs1(1, 0);
f[1] = dp[1];///初始化
dfs2(1, 0);
for (int i = 1;i <= n;i++) cout << f[i] << '\n';
return 0;
}
NC19782 Tree的更多相关文章
- [数据结构]——二叉树(Binary Tree)、二叉搜索树(Binary Search Tree)及其衍生算法
二叉树(Binary Tree)是最简单的树形数据结构,然而却十分精妙.其衍生出各种算法,以致于占据了数据结构的半壁江山.STL中大名顶顶的关联容器--集合(set).映射(map)便是使用二叉树实现 ...
- SAP CRM 树视图(TREE VIEW)
树视图可以用于表示数据的层次. 例如:SAP CRM中的组织结构数据可以表示为树视图. 在SAP CRM Web UI的术语当中,没有像表视图(table view)或者表单视图(form view) ...
- 无限分级和tree结构数据增删改【提供Demo下载】
无限分级 很多时候我们不确定等级关系的层级,这个时候就需要用到无限分级了. 说到无限分级,又要扯到递归调用了.(据说频繁递归是很耗性能的),在此我们需要先设计好表机构,用来存储无限分级的数据.当然,以 ...
- 2000条你应知的WPF小姿势 基础篇<45-50 Visual Tree&Logic Tree 附带两个小工具>
在正文开始之前需要介绍一个人:Sean Sexton. 来自明尼苏达双城的软件工程师.最为出色的是他维护了两个博客:2,000Things You Should Know About C# 和 2,0 ...
- Leetcode 笔记 110 - Balanced Binary Tree
题目链接:Balanced Binary Tree | LeetCode OJ Given a binary tree, determine if it is height-balanced. For ...
- Leetcode 笔记 100 - Same Tree
题目链接:Same Tree | LeetCode OJ Given two binary trees, write a function to check if they are equal or ...
- Leetcode 笔记 99 - Recover Binary Search Tree
题目链接:Recover Binary Search Tree | LeetCode OJ Two elements of a binary search tree (BST) are swapped ...
- Leetcode 笔记 98 - Validate Binary Search Tree
题目链接:Validate Binary Search Tree | LeetCode OJ Given a binary tree, determine if it is a valid binar ...
- Leetcode 笔记 101 - Symmetric Tree
题目链接:Symmetric Tree | LeetCode OJ Given a binary tree, check whether it is a mirror of itself (ie, s ...
- Tree树节点选中及取消和指定节点的隐藏
指定节点变色 指定节点隐藏 单击节点 未选中则选中该节点 已选中则取消该节点 前台: 1.HTML <ul id="listDept" name="listDept ...
随机推荐
- Postman 接口测试配置 Pre-request Script
本文为博主原创,转载请注明出处: Pre-request Script 为Postman预置脚本,用于在postman 发送请求之前执行,封装计算或获取某些请求参数. 1. postman 脚本提供 ...
- 【C++】类大小
[来源]C++类大小详尽讲解 [来源]空类(empty class)
- Vue- 绑定的图片不显示
需要通过 require包裹 <template> <div> {{user.username}}: <img :src="user.avatar" ...
- SpringMVC - 加载静态资源
静态资源过滤 spring-config.xml <!-- 3,(1)让Spring MVC不处理静态资源 .(2)加载静态资源,也称为资源过滤 --> <mvc:default-s ...
- [转帖]idea配置tomcat参数,防止nvarchar保存韩文、俄文、日文等乱码
描述下我的场景: 数据库服务器在远程机器上,数据库使用的Oracle,字符集是ZHS16GBK,但保存韩文.俄文.日文等字段A的数据类型是nvarchar(120),而nvarchar使用的是Unic ...
- Oceanbase开源版 数据库恢复MySQL数据库的过程
# Oceanbase开源版 数据库恢复MySQL数据库的过程 背景 想进行一下Oceanbase数据库的兼容性验证. 想着用app create 数据库的方式周期比较长. 所以我想着换一套 备份恢复 ...
- [转帖]decimal and numeric (Transact-SQL)
https://learn.microsoft.com/en-us/sql/t-sql/data-types/decimal-and-numeric-transact-sql?view=sql-ser ...
- [转帖]正则表达式及在Jmeter中的应用
目录 1.正则表达式 1.1 什么是正则表达式 1.2 为什么使用正则表达式 2.语法 2.1 普通字符 2.2 限定符 2.3 非打印字符 2.4 特殊字符 2.5 定位符 2.6 修饰符(标记) ...
- [转帖]vm内核参数之缓存回收drop_caches
注:本文分析基于3.10.0-693.el7内核版本,即CentOS 7.4 1.关于drop_caches 通常在内存不足时,我们习惯通过echo 3 > /proc/sys/vm/drop_ ...
- docker -- images镜像消失问题排查
1. 问题描叙 安装model-serving组件时,错误日志输出push时对应的tag不存在,导致镜像推送失败 2. 问题排查 # 找到对应镜像,尝试手动推送 docker images|grep ...