图论:Prufer编码
BZOJ1211:使用prufer编码解决限定结点度数的树的计数问题
首先学习一下prufer编码是干什么用的
prufer编码可以与无根树形成一一对应的关系
一种无根树就对应了一种prufer编码
先介绍编码过程:
选择无根树中度数为1的最小编号节点(也就是编号最小的叶子节点),将其删除,把它的邻接点加入数组
不断执行上述操作直到树中仅剩两个节点
解码过程:
顺序扫描prufer编码数组,将扫到的第一个节点记为节点u,寻找不在prufer编码中的没有被标记的最小编号的节点v
连接u-v并把v标记,将u从prufer编码数组删除并扫描下一个节点
性质:
一个点的入度为d,那么它最多有可能在prufer编码中出现d-1次
prufer编码一共有n-2个数字,每个相同的数字出现d-1次
针对这道题,如果我们给出了每个点的度数要求,那么满足要求的树的个数就是可生成的不同的prufer编码的个数:
(n - ) ! / ( (d1 - )! (d2 - )! ……(dn - )! )
这样就是答案了
下面介绍题目的实现方法(这个题比较简单,只是借助了prufer编码的性质进行计数,不涉及编码和解码的过程)
const int maxn=;
int n,tot,cnt;
int pri[maxn],d[maxn],num[maxn];
long long ans=;
long long s[];
tot用来统计prufer编码中应有的节点数,看是否满足等于n-2
cnt用来计数素数的个数,便于分解质因数
pri里存的的是每一个质数,num里存的是质数出现的次数
s用来预处理阶乘
抛开这道题,我们重点应该学一学这个分解质因数的方法
void solve(long long x,int f) //按照指数分解质因数
{
for(int i=;i<=cnt;i++)
{
if(x<=) return;
while(x%pri[i]==) {num[i]+=f;x/=pri[i];}
}
}
满足题目的需求,直接计数即可:
solve(s[n-],); //计算阶乘并将结果分解质因数
for(int i=;i<=n;i++) solve(s[d[i]],-); //同上
for(int i=;i<=cnt;i++)
while(num[i]--) ans*=pri[i]; //统计结果
printf("%lld",ans);
下面给完整的代码:
#include<cmath>
#include<cstdio>
const int maxn=;
int n,tot,cnt;
int pri[maxn],d[maxn],num[maxn];
long long ans=;
long long s[];
inline int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>'') {if(ch=='-')f=-; ch=getchar();}
while(ch>=''&&ch<='') {x*=;x+=ch-'';ch=getchar();}
return x*f;
}
bool jud(int x)
{
for(int i=;i<=sqrt(x);i++)
if(x%i==) return ;
return ;
}
void getpri()
{
for(int i=;i<=;i++)
if(jud(i)) pri[++cnt]=i;
}
void solve(long long x,int f) //按照指数分解质因数
{
for(int i=;i<=cnt;i++)
{
if(x<=) return;
while(x%pri[i]==) {num[i]+=f;x/=pri[i];}
}
}
int main()
{
s[]=;
for(int i=;i<=;i++) s[i]=s[i-]*i;
getpri();
n=read();
if(n==)
{
int x=read();
if(x==) printf("");
else printf("");
return ;
}
for(int i=;i<=n;i++)
{
d[i]=read();
if(d[i]==) {printf("");return ;}
d[i]--;
tot+=d[i];
}
if(tot!=n-) {printf(""); return ;}
solve(s[n-],); //计算阶乘并将结果分解质因数
for(int i=;i<=n;i++) solve(s[d[i]],-); //同上
for(int i=;i<=cnt;i++)
while(num[i]--) ans*=pri[i]; //统计结果
printf("%lld",ans);
return ;
}
图论:Prufer编码的更多相关文章
- 图论:Prufer编码-Cayley定理
BZOJ1430:运用Cayley定理解决树的形态统计问题 由Prufer编码可以引申出来一个定理:Cayley 内容是不同的n结点标号的树的数量为n^(n-2) 换一种说法就是一棵无根树,当知道结点 ...
- 树的prufer编码
prufer是无根树的一种编码方式,一棵无根树和一个prufer编码唯一对应,也就是一棵树有唯一的prufer编码,而一个prufer编码对应一棵唯一的树. 第一部分:树编码成prufer序列. 树编 ...
- 【转】prufer编码
既然有人提到了,就顺便学习一下吧,来源:http://greatkongxin.blog.163.com/blog/static/170097125201172483025666/ 一个含有n个点的完 ...
- [BZOJ1430] 小猴打架 (prufer编码)
Description 一开始森林里面有N只互不相识的小猴子,它们经常打架,但打架的双方都必须不是好朋友.每次打完架后,打架的双方以及它们的好朋友就会互相认识,成为好朋友.经过N-1次打架之后,整个森 ...
- Codeforces 1109D. Sasha and Interesting Fact from Graph Theory 排列组合,Prufer编码
原文链接https://www.cnblogs.com/zhouzhendong/p/CF1109D.html 题意 所有边权都是 [1,m] 中的整数的所有 n 个点的树中,点 a 到点 b 的距离 ...
- prufer编码
看51nod的一场比赛,发现不会大家都A的一道题,有关prufer的 我去年4月就埋下prufer这个坑,一直没解决 prufer编码是什么 对于一棵无根树的生成的序列,prufer序列可以和无根树一 ...
- [bzoj1005][HNOI2008]明明的烦恼-Prufer编码+高精度
Brief Description 给出标号为1到N的点,以及某些点最终的度数,允许在 任意两点间连线,可产生多少棵度数满足要求的树? Algorithm Design 结论题. 首先可以参考这篇文章 ...
- BZOJ 1430 小猴打架(prufer编码)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1430 [题目大意] 一开始森林里面有N只互不相识的小猴子,它们经常打架, 但打架的双方 ...
- 【Foreign】树 [prufer编码][DP]
树 Time Limit: 10 Sec Memory Limit: 256 MB Description Input Output Sample Input 3 2 2 1 Sample Outp ...
随机推荐
- 六:YARN Node Labels
参考:http://dongxicheng.org/mapreduce-nextgen/hadoop-yarn-label-based-scheduling/ 为不同的DATANODE打标签,通过标签 ...
- OpenCV学习5-----使用Mat合并多张图像
最近做实验需要对比实验结果,需要将几张图片拼在一起,直观对比. 尝试用OpenCV解决. 核心思想其实是 声明一个足够大的,正好容纳下那几张图片的mat,然后将拼图依次copy到大图片相应的位置. ...
- eg_4
4. 编写一个程序,要求以树状结构展现特定的文件夹及其子文件(夹) import java.io.*; public class Test { public static void main(Stri ...
- <Effective C++>读书摘要--Designs and Declarations<一>
<Item 18> Make interfaces easy to use correctly and hard to use incorrectly 1.That being the c ...
- Python对字符串进行MD5加密处理
import hashlibimport sysreload(sys)sys.setdefaultencoding('utf-8') m = hashlib.md5()m.update('123456 ...
- Django 2.0 学习(10):Django 定制化
定制化admin表单 通过使用admin.site.register(Question)注册Question模型,Django可以构造默认的表单.通常,可以通过对象的注册机制来告诉Django我们想要 ...
- hdu 1054 Strategic Game (二分匹配)
Strategic Game Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) ...
- libsvm 用在 婚介数据集中 预测 用户配对
分类前具备的数据集: 书本第九章数据集(训练集):agesonly.csv和matchmaker.csv. agesonly.csv 格式是: 男年龄,女年龄,是否匹配成功 24,30,1 30,4 ...
- CF757G Can Bash Save the Day?
CF757G Can Bash Save the Day? #include<bits/stdc++.h> #define RG register #define IL inline #d ...
- ural1297 求最长回文子串 | 后缀数组
#include<cstdio> #include<algorithm> #include<cstring> #define N 20005 using names ...