[BZOJ4632]树的编码

试题描述

SHUXK 正在对一棵N个结点的有根树进行研究,首要的一件事就是对这棵树进行编码。
lz 说:“这还不容易吗?我令根节点的编号为 1,然后保证每个结点的编号都比它的父亲结点的编号大。这样不
就行了吗?”但 SHUXK 对这种编码方案并不满意,因为没什么特色,从中也得不到什么有用的信息。于是他想出
了一种新的编码,这种编码需要满足两个条件:
1. 作为一个 OIer,应该保证每个结点的编码是一个 01 串;
2. 为了体现树的特点,假设??号结点的编码为Si,应该有如下性质:
如果结点U是结点V的祖先,那么Su就应该是Sv的前缀;
如果结点U不是结点V的祖先或后代,那么Su就不允许是Sv的前缀。
lz 说:“ 这样编码确实有特色。 但是这样一来,编码会很长呀!”
SHUXK 说:“我们就来求一种最优的编码,使得所有结点的编码长度之和最小。”当然, lz 和 SHUXK 都已经从 
OI 界退役了,他们讨论完了以后就把这个任务交给你了。

输入

输入文件的第一行包含一个正整数N(N<=10^5),表示棋盘的大小。
第二行包含N - 1个整数, 分别表示2~N号结点的父亲结点Fi( 保证Fi<i,也就是说 lz 已经编码好了)。

输出

输出文件只有一行一个整数, 表示所有结点编码长度之和的最小值。

输入示例

   

输出示例


数据规模及约定

见“输入

题解

考虑菊花图,即只有 2 层的情况,那么就是贪心地合并,每次合并的代价为两个集合大小总和,合并之后删掉原来两个集合,添加一个新集合,其大小等于两集合大小总和。仔细想想便知,这里所花的“代价”即为所用编码的长度。那么策略是每次找到两个最小的集合合并,用堆维护即可。

现在问题是对于一个节点,它有许多孩子,每个儿子节点 i 有一个子树大小 siz[i]。不难发现我们可以继续上面的合并,即从下而上按照上面的策略合并。一个子树内所对应的所有集合合并后大小即为该子树大小。所以以子树大小为关键字每次找到两个最小的集合合并,累计答案。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <cstring>
#include <string>
#include <map>
#include <set>
using namespace std; const int BufferSize = 1 << 16;
char buffer[BufferSize], *Head, *Tail;
inline char Getchar() {
if(Head == Tail) {
int l = fread(buffer, 1, BufferSize, stdin);
Tail = (Head = buffer) + l;
}
return *Head++;
}
int read() {
int x = 0, f = 1; char c = Getchar();
while(!isdigit(c)){ if(c == '-') f = -1; c = Getchar(); }
while(isdigit(c)){ x = x * 10 + c - '0'; c = Getchar(); }
return x * f;
} #define maxn 100010
#define maxm 200010
int n, m, fa[maxn], head[maxn], next[maxm], to[maxm]; void AddEdge(int a, int b) {
to[++m] = b; next[m] = head[a]; head[a] = m;
swap(a, b);
to[++m] = b; next[m] = head[a]; head[a] = m;
return ;
} priority_queue <int> Q;
int siz[maxn], ans;
void build(int u) {
siz[u] = 1;
for(int e = head[u]; e; e = next[e]) if(to[e] != fa[u]) {
build(to[e]);
siz[u] += siz[to[e]];
}
for(int e = head[u]; e; e = next[e]) if(to[e] != fa[u]) Q.push(-siz[to[e]]);
while(!Q.empty()) {
int u1 = -Q.top(), u2; Q.pop();
if(Q.empty()) break;
u2 = -Q.top(); Q.pop();
Q.push(-u1 - u2);
ans += u1 + u2;
}
return ;
} int main() {
n = read();
for(int i = 2; i <= n; i++) AddEdge(i, fa[i] = read()); build(1); printf("%d\n", ans); return 0;
}

[BZOJ4632]树的编码的更多相关文章

  1. Huffman树的编码译码

    上个学期做的课程设计,关于Huffman树的编码译码. 要求: 输入Huffman树各个叶结点的字符和权值,建立Huffman树并执行编码操作 输入一行仅由01组成的电文字符串,根据建立的Huffma ...

  2. Huffman树进行编码和译码

    //编码#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> ...

  3. Huffman树与编码

    带权路径最小的二叉树称为最优二叉树或Huffman(哈夫曼树). Huffman树的构造 将节点的权值存入数组中,由数组开始构造Huffman树.初始化指针数组,指针指向含有权值的孤立节点. b = ...

  4. 【Foreign】树 [prufer编码][DP]

    树 Time Limit: 10 Sec  Memory Limit: 256 MB Description Input Output Sample Input 3 2 2 1 Sample Outp ...

  5. Huffman树及其编码(STL array实现)

    这篇随笔主要是Huffman编码,构建哈夫曼树有各种各样的实现方法,如优先队列,数组构成的树等,但本质都是堆. 这里我用数组来存储数据,以堆的思想来构建一个哈弗曼树,并存入vector中,进而实现哈夫 ...

  6. Huffman树与编码的简单实现

    好久没写代码了,这个是一个朋友问的要C实现,由于不会C,就用JAVA写了个简单的.注释掉的代码属性按照原来朋友发的题里带的参数,发现没什么用就给注释掉了. package other; import ...

  7. 「模拟赛20180406」膜树 prufer编码+概率

    题目描述 给定一个完全图,保证\(w_{u,v}=w_{v,u}\)且\(w_{u,u}=0\),等概率选取一个随机生成树,对于每一对\((u,v)\),求\(dis(u,v)\)的期望值对\(998 ...

  8. deflate树与deflate编码

    关于deflate树,能搜到的资料非常少,这个概念来自gzip的压缩算法,是由huffman树转变过来的.这里简单记录下deflate树的生成过程以及deflate编码. 假设以5 8 9 10 14 ...

  9. bzoj1211: [HNOI2004]树的计数(purfer编码)

    BZOJ1005的弱化版,不想写高精度就可以写这题嘿嘿嘿 purfer编码如何生成?每次将字典序最小的叶子节点删去并将其相连的点加入序列中,直到树上剩下两个节点,所以一棵有n个节点的树purfer编码 ...

随机推荐

  1. linux下定时任务的使用

    使用方法 执行crontab -e命令会进入一个可编辑界面,在该界面中我们可以制定定时任务,然后保存退出(wq) 格式如下: 由于直接运行编辑命令后只是一个空白界面,不够友好,所以建议使用以下方式来增 ...

  2. 每天一个linux命令(34):kill命令

    Linux 中的kill命令用来终止指定的进程(terminate a process)的运行,是Linux下进程管理的常用命令.通常,终止一个前台进程可以 使用Ctrl+C键,但是,对于一个后台进程 ...

  3. JS高级设计第七章——复习知识点

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  4. A星寻路算法

    A星寻路算法 1.准备一个close关闭列表(存放已被检索的点),一个open开启列表(存放未被检索的点),一个当前点的对象cur 2.将cur设成开始点 3.从cur起,将cur点放入close表中 ...

  5. BIEE连接数据库的方法

    BI创建(数据)分析.仪表盘.报表前,都需要对数据进行建模,在oracle biee里称为创建“资料档案库”-该文件后缀为RPD,所以一般也称为创建RPD文件. 步骤: 1.从windows开始菜单里 ...

  6. BZOJ1034 [ZJOI2008]泡泡堂BNB

    Description 第XXXX届NOI期间,为了加强各省选手之间的交流,组委会决定组织一场省际电子竞技大赛,每一个省的代表 队由n名选手组成,比赛的项目是老少咸宜的网络游戏泡泡堂.每一场比赛前,对 ...

  7. TCP/IP详解 学习七

    静态选路的前提: 1)         网络比较小 2)         网络之间单点连接 3)         网络之间没有多余的路由 动态选路协议,用于路由器之间的通信,有以下几种: 1)     ...

  8. codeforce626D (概率)

    D. Jerry's Protest time limit per test 2 seconds memory limit per test 256 megabytes input standard ...

  9. 修改host

    需修改手机/etc/hosts文件.将” 118.194.60.190 域名” 添加 手机的/etc/hosts文件.手机需有root权限,操作如下:1. C:\Documents and Setti ...

  10. mongodb(基础用法)

    驱动和客户端库 https://mongodb-documentation.readthedocs.org/en/latest/ecosystem/drivers.html#id2 https://m ...