[BZOJ:3162]:独钓寒江雪


题解:
求本质不同的独立集的个数
首先独立集的个数是很好做的
\(f[u][0/1]\)表示节点\(u\)不选/选的方案数
然后dp就是
\(f[u][0] = f[u][0] * (f[v][0] + f[v][1])\)
\(f[u][1] = f[u][1] * f[v][0]\)
考虑怎么去重
不论把这个树怎么转或者以哪一个点为根
最后重心肯定不会变
所以我们可以把重心拎出来当根
一般在树上求本质不同的东西可以优先考虑重心
然后如果有两个重心(最多肯定只有两个==)那么这两个重心肯定由一条边连着
就可以新建一个节点连向这两个重心
然后dp
在dp计数的时候
如果\(k\)个子树\(v\)是本质上相同的
那么这\(k\)个子树的贡献总和就是就是\(C(f[v][0] + (f[v][1]) + k - 1 , k)\)
要求的是本质不同的独立集
所以就相当于可以随意编号
那么我们假设有n个子树,每个子树都有m个方案
那么我们按照选择的方案排序后如果相同就是重复的
所以我们就让后面的每一个选择的方案编号都比前一个大
这样就相当于方程整数解问题了
还有一个问题就是这个组合数怎么算?
因为k不大但是前面那个东西太大了
所以我们就相当于把\(C(n,m)\)底下那个\((n-m)!\)和上面的约分
那么就变成了\(\frac{n * (n - 1) * .. * (n - m + 1)}{m!}\)
然后注意这题卡哈希卡的挺厉害
最后换成我的生日才过的
代码
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
# define LL long long
# define ull unsigned long long
const int M = 500005 ;
const long long mod = 1e9 + 7 ;
const long long INF = 1e9 ;
const ull Base = 23333333333ULL ;
using namespace std ;
inline int read() {
char c = getchar() ; int x = 0 , w = 1 ;
while(c>'9'||c<'0') { if(c=='-') w = -1 ; c = getchar() ; }
while(c >='0' && c<='9') { x = x*10+c-'0' ; c = getchar() ; }
return x*w ;
}
int n , num = 1 , hea[M] ;
int size[M] , sonsz[M] , tmx = INF , rtnum , rt[M] , st[M] ;
long long fac[M] , finv[M] ;
LL f[M][2] ;
ull hsh[M] ;
struct E { int nxt , to ; } edge[M << 1] ;
inline void add_edge(int from , int to) {
edge[++num].nxt = hea[from] ;
edge[num].to = to ; hea[from] = num ;
}
inline bool Cmp(int a , int b) {
if(hsh[a] == hsh[b]) return ((f[a][0] + f[a][1]) % mod < (f[b][0] + f[b][1]) % mod) ;
return hsh[a] < hsh[b] ;
}
inline bool Same(int a , int b) {
if(hsh[a] == hsh[b] && ((f[a][0] + f[a][1]) % mod) == ((f[b][0] + f[b][1]) % mod)) return true ;
return false ;
}
inline long long Fpw(long long Base , int k) {
long long temp = 1 ;
while(k) {
if(k & 1) temp = (temp * Base) % mod ;
Base = (Base * Base) % mod ; k >>= 1 ;
}
return temp ;
}
void Grt(int u , int father) {
size[u] = 1 ; int Mx = -1 ;
for(int i = hea[u] ; i ; i = edge[i].nxt) {
int v = edge[i].to ; if(v == father) continue ;
Grt(v , u) ; size[u] += size[v] ; Mx = max(Mx , size[v]) ;
}
Mx = max(Mx , n - size[u]) ; sonsz[u] = Mx ; tmx = min(tmx , Mx) ;
}
inline long long C(long long n , int m) {
n %= mod ; if(n < m) return 0 ; long long Ans = 1 ; m = min(1LL * m , n - m) ;
for(int i = n ; i >= n - m + 1 ; i --) Ans = (1LL * Ans * i) % mod ;
Ans = (Ans * finv[m]) % mod ; return Ans ;
}
void Dfs(int u , int father) {
f[u][0] = f[u][1] = 1 ;
for(int i = hea[u] ; i ; i = edge[i].nxt) {
int v = edge[i].to ; if(v == father) continue ;
Dfs(v , u) ;
}
int top = 0 ;
for(int i = hea[u] ; i ; i = edge[i].nxt) {
int v = edge[i].to ; if(v == father) continue ;
st[++top] = v ;
}
sort(st + 1 , st + top + 1 , Cmp) ;
int l = 1 , r = 0 ;
for(int v ; l <= top ; l = r + 1) {
for(r = l ; r <= top ; r ++) {
if(!Same(st[l] , st[r]))
break ;
}
r -- ;
v = st[l] ;
f[u][1] = (f[u][1] * C(f[v][0] + r - l , r - l + 1)) % mod ;
f[u][0] = (f[u][0] * C(f[v][0] + f[v][1] + r - l , r - l + 1)) % mod ;
}
ull tmp = 0 ;
for(int i = 1 ; i <= top ; i ++)
tmp = (tmp * Base + (hsh[st[i]] + i) * 20020911uLL) ;
hsh[u] = tmp ;
}
int main() {
n = read() ; fac[0] = 1 ; finv[0] = 1 ;
for(int i = 1 ; i <= n ; i ++) {
fac[i] = (fac[i - 1] * i) % mod ;
finv[i] = Fpw(fac[i] , mod - 2) ;
}
for(int i = 1 , u , v; i < n ; i ++) {
u = read() , v = read() ;
add_edge(u , v) ; add_edge(v , u) ;
}
Grt(1 , 1) ;
for(int i = 1 ; i <= n ; i ++)
if(sonsz[i] == tmx)
rt[++rtnum] = i ;
int k = rt[1] ;
for(int i = hea[rt[1]] ; i ; i = edge[i].nxt) {
int v = edge[i].to ;
if(v == rt[2]) {
k = n + 1 ;
edge[i].to = edge[i ^ 1].to = k ;
break ;
}
}
if(rtnum > 1) {
add_edge(k , rt[1]) ;
add_edge(k , rt[2]) ;
}
Dfs(k , k) ;
if(rtnum == 1) printf("%lld\n",(f[rt[1]][0] + f[rt[1]][1] + mod) % mod) ;
else if(rtnum == 2) {
int x = rt[1] , y = rt[2] ;
if(hsh[x] != hsh[y])
printf("%lld\n",(f[x][0] * f[y][0] + f[x][0] * f[y][1] + f[x][1] * f[y][0]) % mod) ;
else printf("%lld\n",(C(f[x][0] + 1 , 2) + f[x][0] * f[y][1]) % mod) ;
}
return 0 ;
}
[BZOJ:3162]:独钓寒江雪的更多相关文章
- BZOJ 3162: 独钓寒江雪 树的同构 + 组合 + 计数
Description Input Output 求一棵树编号序列不同的方案数: 令 $f[u],g[u]$ 分别表示 $u$ 选/不选 的方案数. 则 $f[u]=\prod_{v\in son ...
- BZOJ 3162 / Luogu P4895: 独钓寒江雪 树hash+DP
题意 给出一棵无根树,求本质不同的独立集数模100000000710000000071000000007的值. n≤500000n\le 500000n≤500000 题解 如果是有根树就好做多了.然 ...
- bzoj AC倒序
Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...
- 【BZOJ3162】独钓寒江雪(树哈希,动态规划)
[BZOJ3162]独钓寒江雪(树哈希,动态规划) 题面 BZOJ 题解 忽然翻到这道题目,突然发现就是前几天一道考试题目... 题解: 树哈希,既然只考虑这一棵树,那么,如果两个点为根是同构的, 他 ...
- [bzoj3162]独钓寒江雪_树hash_树形dp
独钓寒江雪 题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3162 题解: 首先,如果没有那个本质相同的限制这就是个傻逼题. 直接树形dp ...
- BZOJ 2127: happiness [最小割]
2127: happiness Time Limit: 51 Sec Memory Limit: 259 MBSubmit: 1815 Solved: 878[Submit][Status][Di ...
- BZOJ 3275: Number
3275: Number Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 874 Solved: 371[Submit][Status][Discus ...
- BZOJ 2879: [Noi2012]美食节
2879: [Noi2012]美食节 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 1834 Solved: 969[Submit][Status] ...
- bzoj 4610 Ceiling Functi
bzoj 4610 Ceiling Functi Description bzoj上的描述有问题 给出\(n\)个长度为\(k\)的数列,将每个数列构成一个二叉搜索树,问有多少颗形态不同的树. Inp ...
随机推荐
- [luoguP1972] [SDOI2009]HH的项链(莫队 || 树状数组 || 主席树)
传送门 莫队基础题,适合我这种初学者. 莫队是离线算法,通常不带修改,时间复杂度为 O(n√n) 我们要先保证通过 [ l , r ] 求得 [ l , r + 1 ] , [ l , r - 1 ] ...
- bzoj 1430 小猴打架 prufer 性质
小猴打架 Time Limit: 5 Sec Memory Limit: 162 MBSubmit: 709 Solved: 512[Submit][Status][Discuss] Descri ...
- cdq分治入门--BZOJ1492: [NOI2007]货币兑换Cash
n<=100000天,一开始有s块钱,每天股票A价格ai,B价格bi,每天可以做的事情:卖出股票:按A:B=RTi的比例买入股票.问最后的最大收益.股票可以为浮点数,答案保留三位. 用脚指头想想 ...
- nyoj_308_Substring_201405091611
Substring 时间限制:1000 ms | 内存限制:65535 KB 难度:1 描述 You are given a string input. You are to ...
- 常用的delphi 第三方控件
Devexpress VCL 这个基本上覆盖了系统界面及数据库展示的方方面面,是做桌面系统必备的一套控件,目前的版本是2011.2.3, 支持win32 及win64. AutoUpgrader 这个 ...
- 洛谷 P1122 最大子树和
P1122 最大子树和 题目描述 小明对数学饱有兴趣,并且是个勤奋好学的学生,总是在课后留在教室向老师请教一些问题.一天他早晨骑车去上课,路上见到一个老伯正在修剪花花草草,顿时想到了一个有关修剪花卉的 ...
- 关于SQL SERVER导出数据的问题!
前面一段时间,为这个导出数据真是煞费苦心,网上找了好多资料都没有找到. 从SQL SERVER 2008开始,我们就可以很方便的导出数据脚本,而无需再借助存储过程,但是SQL Server 2012和 ...
- 条款五:对应的new和delete要采用相同的形式
string *stringarray = new string[100]; ... delete stringarray; 上述程序的运行情况将是不可预测的.至少,stringarray指向的100 ...
- react 项目实战(四)组件化表单/表单控件 高阶组件
高阶组件:formProvider 高阶组件就是返回组件的组件(函数) 为什么要通过一个组件去返回另一个组件? 使用高阶组件可以在不修改原组件代码的情况下,修改原组件的行为或增强功能. 我们现在已经有 ...
- 网上Unused Index Script 脚本的问题
曾经使用过网上下载的脚本查询没有使用过的Index比方SQL SERVER – 2008 – Unused Index Script – Download,事实上如今看起来这个脚本是有一些问题. 脚本 ...