独钓寒江雪

题目背景:

bzoj3162

分析:哈希 + 树型DP

从这道题上感觉到了深深的绝望······在OJ上一直都是12msWA,一直不知道怎么搞的,造的500000随机数据怎么跑怎么过······拍了几百组都没有锅,最后突然奇想造了条链,然后炸了······然后改小数据范围10000WA了,100WA了,10WA了,5WA了······然后手调一下发现我的hash函数和size有关,然后找到重心换根后没有更新过size······然后就这样炸掉了,随机数据好像大部分都是以1为根,竟然就活的上好······不说了

讲题,首先我们对于独立点集的求取应该非常简单吧,定义f[i][0/1]表示i(不是/是)极寒点的方案数,显然f[i][0]为i所有的儿子v的(f[v][0] + f[v][1])之积,f[i][1]为所有f[v][0]之积,考虑如何保证结构,显然,我们会想到树hash来维护同构,那么我们只需要定义hash函数,若hash[i] == hash[j]则表示两者结构相同,那么只要定一个能够保证这个条件的又不易冲突的hash函数即可,并且我们DP的开始位置一定要是重心,因为其他点是可能变化的,但是重心肯定还是那两个,再者,如果出现了子树完全同构的情况,比如这种子树有m个,可行的构造方案n种那么这一块的总方案有C(n + m - 1, m)种,然后根据乘法原理就可以直接DP了。

Source:

/*created by scarlyw
*/
#include <cstdio>
#include <string>
#include <algorithm>
#include <cstring>
#include <iostream>
#include <cmath>
#include <cctype>
#include <vector>
#include <set>
#include <queue>const int MAXN = 500000 + 10;
const long long mod = 1000000000 + 7;
const unsigned long long base = 233;int n, x, y, c1, c2, ans;
long long inv[MAXN], size[MAXN], f[MAXN][2];
unsigned long long hash[MAXN], hash_pow[MAXN];
std::vector<int> edge[MAXN];inline void add_edge(int x, int y) {edge[x].push_back(y), edge[y].push_back(x);
}inline void pre_work() {inv[1] = 1, hash_pow[0] = 1;for (int i = 2; i <= n; ++i) inv[i] = (long long)(-mod / i + mod) * inv[mod % i] % mod;for (int i = 1; i <= n; ++i) hash_pow[i] = hash_pow[i - 1] * base;
}inline void read_in() {scanf("%d", &n);for (int i = 1; i < n; ++i) scanf("%d%d", &x, &y), add_edge(x, y);
}inline void dfs_root(int cur, int fa) {size[cur] = 1;bool flag = true;for (int p = 0; p < edge[cur].size(); ++p) {int v = edge[cur][p];if (v != fa) {dfs_root(v, cur), size[cur] += size[v];if (2 * size[v] > n) flag = false;}}if (size[cur] * 2 < n) flag = false;if (flag) (c1 == 0 ? c1 = cur : c2 = cur);
}inline bool comp(const int &a, const int &b) {return hash[a] < hash[b];
}inline long long c(long long n, int m) {long long ans = 1;n %= mod;for (int i = 1; i <= m; ++i) ans = ans * (n + 1LL - i) % mod * inv[i] % mod;return ans;
}inline void dfs(int cur, int fa) {static int stack[MAXN];int top = 0, j, v;hash[cur] = hash_pow[0], size[cur] = 1;for (int p = 0; p < edge[cur].size(); ++p) {int v = edge[cur][p];if (v != fa) {dfs(v, cur), size[cur] += size[v];hash[cur] += hash_pow[size[v]] * hash[v];}}for (int p = 0; p < edge[cur].size(); ++p) {int v = edge[cur][p];if (v != fa) stack[++top] = v;}f[cur][0] = f[cur][1] = 1;std::sort(stack + 1, stack + top + 1, comp);for (int i = 1; i <= top; i = j) {for (v = stack[i], j = i + 1; j <= top && hash[stack[i]] == hash[stack[j]]; ++j);f[cur][0] = f[cur][0] * c(j - i - 1 + f[v][0] + f[v][1], j - i) % mod;f[cur][1] = f[cur][1] * c(j - i - 1 + f[v][0], j - i) % mod;}
}inline void solve() {read_in(), dfs_root(1, 1), pre_work();(c2 ? (dfs(c1, c2), dfs(c2, c1)) : (dfs(c1, c1)));if (c2) {if (hash[c1] != hash[c2]) { ans = (f[c1][0] * f[c2][0] + f[c1][1] * f[c2][0] + f[c1][0] * f[c2][1]) % mod;} else ans = (f[c1][0] * f[c2][1] + c(f[c1][0] + 1, 2)) % mod;} else ans = (f[c1][0] + f[c1][1]) % mod;printf("%d", ans);
}int main() {solve();return 0;
}

bzoj3162 独钓寒江雪相关推荐

  1. 洛谷4895 BZOJ3162 独钓寒江雪 树形dp 树哈希

    题目链接 题意: 给定一棵无根树,求其中本质不同的独立集的个数.独立集就是一个集合中的点之间都没有边直接相连.n<=5e5n<=5e5n<=5e5,对1e9+71e9+71e9+7取 ...

  2. bzoj3162 独钓寒江雪(树形dp+Hash)

    就是求无根树的本质不同的独立集个数.如果不考虑本质不同,则有树形dp. 考虑本质不同,就要考虑无根树的同构,可以用hash来搞.具体题解见:portal 我的hash真是冲突到死[再见],hash值最 ...

  3. BZOJ3162 独钓寒江雪【无根树同构问题】

    题目描述: 给定一棵无根树,求其中本质不同的独立集的个数. n<=500000 题目分析: 如果任选一点作根,那么它选1的情况和它选0的情况有可能是本质相同的. 但如果选重心作根(如果有两个重心 ...

  4. Noip前的大抱佛脚----赛前任务

    赛前任务 tags:任务清单 前言 现在xzy太弱了,而且他最近越来越弱了,天天被爆踩,天天被爆踩 题单不会在作业部落发布,所以可(yi)能(ding)会不及时更新 省选前的练习莫名其妙地成为了Noi ...

  5. BZOJ 3162 独钓寒江雪(树同构计数)

    给定一棵无根树,求其中本质不同的独立集的个数. 无根树同构. 转化成以重心为根的有根树,如果重心有两个,就在这两个重心之间插入一个点与这两个重心连边,这个点作为新的重心. 然后就成了有根树同构过程树形 ...

  6. BZOJ 3162: 独钓寒江雪 树的同构 + 组合 + 计数

    Description Input Output 求一棵树编号序列不同的方案数: 令 $f[u],g[u]$ 分别表示 $u$ 选/不选 的方案数. 则 $f[u]=\prod_{v\in son[u ...

  7. 洛谷4895 独钓寒江雪 (树哈希+dp+组合)

    qwq 首先,如果是没有要求本质不同的话,那么还是比较简单的一个树形dp 我们令dp[i][0/1]dp[i][0/1]dp[i][0/1]表示是否iii的子树,是否选iii这个点的方案数. 一个比较 ...

  8. bzoj 3162: 独钓寒江雪 树哈希+树形dp

    题意 给出一棵无标号无根树,问本质不同的最大独立集数量.答案模1e9+7. n<=500000 分析 对于一般的情况,我们可以先找出树的重心作为根,然后进行树形dp.这样做有什么好处呢?通过根的 ...

  9. 使用openpyxl去操作Excel表格

    对表格的数据写操作: from openpyxl import Workbook wb=Workbook()w1=wb.create_sheet('index',0) # w1["E4&qu ...

  10. C# 操作Sql Server 学习总结

    C#中产生SQL语句的几种方式 (1)拼接产生SQL语句: string sql = "insert into czyb(yhm,mm,qx) values('" + txtNam ...

最新文章

  1. linux定时任务简记
  2. 一段代码到可执行程序所有经历
  3. vue下拉框值改变_vue select下拉框绑定值不跟着变问题
  4. java.lang.NumberFormatException: For input string: F
  5. spring boot处理请求返回值的格式(自定义消息转换器)
  6. 蒙古族女孩鲍尔金娜的小说《紫茗红菱》
  7. flutter网络请求dio的get、post、上传文件、下载文件总结
  8. UEFI---(NT32)的第一个代码
  9. 剑指Offer(Java版):二叉搜索树的后序遍历序列
  10. 略谈人工智能算法的缺点
  11. 基于Matlab的随机信号分析
  12. IndentationError:unindent does not match any outer indentation解决方案
  13. 02_函数定义及使用函数
  14. 打破双亲委派么,怎么打破_打破统一垃圾收集规则
  15. Webx系列之文件下载
  16. stm32语音识别文字显示_『开源项目』基于STM32的智能垃圾桶之语音识别
  17. 2018清华计算机类专业录取分数线,2020清华大学录取分数线汇总(含2018-2019历年)...
  18. 如何解决用户出差,脱域的问题
  19. ROS中的Client Library与roscpp talker lisener
  20. 解码 解密微信电脑版image文件夹下缓存的用户图片 dat文件解码解密查看方法

热门文章

  1. oracle现金流量表逻辑,财务学习:现金流量表内在逻辑研究
  2. 注册微信小程序账号 APPID的获取
  3. 关于在线答题系统设计的一些想法
  4. 【SVM分类】基于遗传算法优化支持向量机实现葡萄酒分类附matlab代码
  5. cad计算机绘注意事项,CAD制图的注意事项
  6. Unity导出exe时遇到的两个问题
  7. java Eclipse 如何打开bin文件目录视图
  8. 2020 愿远方依旧有篮球为伴 致敬24号 科比
  9. 计算机待机英语,计算机休眠
  10. corutine rust_rust 异步 IO:从 mio 到 coroutine