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 ...
随机推荐
- 18-CMOS门电路
CMOS门电路 TTL是三极管构成的门电路,逐步被CMOS电路替代.CMOS电路能耗低.集成度高. CMOS反相器 CMOS管是由PMOS和NMOS组成,这里用的都是使用的增强型. COMS能够正常工 ...
- [kubernetes]安装dashboard
前言 kubernetes官方文档中的web UI网页管理工具是kubernetes-dashboard,可提供部署应用.资源对象管理.容器日志查询.系统监控等常用的集群管理功能.为了在页面上显示系统 ...
- [转帖]fullgc问题解决:Full GC (Metadata GC Threshold)
#问题描述 在工作过程中,遇到一个问题:Tomcat在重启或者发布的时候,会有多次的full GC. 笔者使用的版本说明: Tomcat7.0.25 JDK8 首先排查JVM的问题,就要把GC日志打开 ...
- [转帖]Jmeter之界面语言设置
https://developer.aliyun.com/article/1173114#:~:text=%E6%B0%B8%E4%B9%85%E6%80%A7%E8%AE%BE%E7%BD%AE%E ...
- 信创CPU与牙膏厂和按摩店CPU的简单对比
信创CPU与牙膏厂和按摩店CPU的简单对比 摘要 周天时学习验证了SPEC2006的工具. 晚上时写完了第一稿简单的使用 因为 SPEC 完整跑完非常漫长. 我想了一下短平快还是通过使用一个简单的 r ...
- awk中的NR,FNR ,NF,$NF,RS,ORS,FS,OFS
awk中的NR,FNR ,NF,$NF,RS,ORS,FS,OFS https://www.cnblogs.com/zhangqingsh/archive/2013/04/24/3040801.htm ...
- linux 查看系统计划任务相关的命令
最近公司排查计划任务: for i in `ls /etc/cron.d` ; do cat /etc/cron.d/$i |grep -v "#" ; done for i in ...
- Mysql到TiDB迁移,双写数据库兜底方案
作者:京东零售 石磊 TiDB 作为开源 NewSQL 数据库的典型代表之一,同样支持 SQL,支持事务 ACID 特性.在通讯协议上,TiDB 选择与 MySQL 完全兼容,并尽可能兼容 MySQL ...
- vue中jsx
//item.vue 文件如下 <template> <div> <h1 v-if="id===1"> <slot></slo ...
- 【JS 逆向百例】某公共资源交易网,公告 URL 参数逆向分析
声明 本文章中所有内容仅供学习交流,抓包内容.敏感网址.数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请联系我立即删除! 逆向目标 目标:某地公共资 ...