[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. C# 无法识别的转义序列

    解决这个问题头两种方法:1.加个"\"进行转义:2.在前面加个@ 示例:我要进入D盘下video文件夹中的ysxs文件夹,写法分别为: D:\\video\\ysxs @" ...

  2. 理解C#事件

    前面文章中介绍了委托相关的概念,委托实例保存这一个或一组操作,程序中将在某个特定的时刻通过委托实例使用这些操作. 如果做过GUI程序开发,可能对上面的描述会比较熟悉.在GUI程序中,单击一个butto ...

  3. WCF 入门 (21)

    前言 再不写一篇就太监了,哈哈. 第21集 WCF里面的Binding Bindings in WCF 其实不太了解为什么第21集才讲这个Binding,下面都是一些概念性的东西,不过作为一个入门视频 ...

  4. 使用GIT来管理代码的心得

    使用GIT来管理代码,第一步当然就是下载一个GIT客户端(不知道是不是这么叫,但是觉得和客户端的功能差不多).电脑的操作系统是windows7的,所以下的是对应的GIT. 就是这玩意,安装的时候不停的 ...

  5. Sublime Text 3 绝对神器

    距第一篇的开箱水文,已经有4个月的时间了,但因为懒,就没有下文了.终于,今天,我觉得写一篇准技术文章了. 忘记了是怎么开始用的ST,应该是在网上看到别人推荐才用到吧,用了有半年了.在windows下是 ...

  6. [转]DIV+CSS和TABLE的区别

    现在全国大大小小的网站都在搞一场技术“革命”,就是所谓“网站重构”说简单点就是DIV+CSS进行网站制作.用DIV+CSS代替传统的Table制作框架和美化页面.百度搜索优化 在重构之前,肯定要了解为 ...

  7. emberJS

    <!doctype html> <html> <head> <meta charset="utf-8"> <title> ...

  8. Java-HashMap和HashTable的区别

    类继承and实现上看 public class Hashtable extends Dictionary implements Map, Cloneable, java.io.Serializable ...

  9. 【bzoj1857】 Scoi2010—传送带

    http://www.lydsy.com/JudgeOnline/problem.php?id=1857 (题目链接) 题意 给出两条线段AB和CD,在AB上的速度为P,在CD上的速度为Q,在AB,C ...

  10. 【bzoj1013】 JSOI2008—球形空间产生器sphere

    www.lydsy.com/JudgeOnline/problem.php?id=1013 (题目链接) 题意 有一个n维的球体,给出球上n+1个点,求出圆心. Solution 题中给出了对于n维空 ...