第五讲 树(下)
05-树7:堆中的路径
Description:
将一系列给定数字插入一个初始为空的小顶堆H[]。随后对任意给定的下标i,打印从H[i]到根结点的路径。
Input:
每组测试第1行包含2个正整数N和M(≤1000),分别是插入元素的个数、以及需要打印的路径条数。下一行给出区间[-10000, 10000]内的N个要被插入一个初始为空的小顶堆的整数。最后一行给出M个下标。
Output:
对输入中给出的每个下标i,在一行中输出从H[i]到根结点的路径上的数据。数字间以1个空格分隔,行末不得有多余空格。
SampleInput:
5 3
46 23 26 24 10
5 4 3
SampleOutput:
24 23 10
46 23 10
26 10
Codes:
//#define LOCAL
#include <cstdio>
#define M 1010
#define S -10010
int i, cnt, A[M] = {S};
void insert(int a) {
for(i=++cnt; A[i/2]>a; i/=2) A[i] = A[i/2];
A[i] = a;
}
int main()
{
#ifdef LOCAL
freopen("E:\\Temp\\input.txt", "r", stdin);
freopen("E:\\Temp\\output.txt", "w", stdout);
#endif
int a, n, m;
scanf("%d%d", &n, &m);
while(n--) { scanf("%d", &a); insert(a); }
while(m--) {
scanf("%d", &a);
printf("%d", A[a]); a /= 2;
while(a) { printf(" %d", A[a]); a /= 2; }
printf("\n");
}
return 0;
}
05-树8:File Transfer.
Description:
We have a network of computers and a list of bi-directional connections. Each of these connections allows a file transfer from one computer to another. Is it possible to send a file from any computer on the network to any other?
Input:
Each input file contains one test case. For each test case, the first line contains N(2, 10^4), the total number of computers in a network. Each computer in the network is then represented by a positive integer between 1 and N. Then in the following lines, the input is given in the format: I c1 c2 where I stands for inputting a connection between c1 and c2; or C c1 c2 where C stands for checking if it is possible to transfer files between c1 and c2; or S where S stands for stopping this case.
Output:
For each C case, print in one line the word "yes" or "no" if it is possible or impossible to transfer files between c1 and c2, respectively. At the end of each case, print in one line "The network is connected." if there is a path between any pair of computers; or "There are k components." where k is the number of connected components in this network.
SampleInput1:
5
C 3 2
I 3 2
C 1 5
I 4 5
I 2 4
C 3 5
S
SampleOutput1:
no
no
yes
There are 2 components.
SampleInput2:
5
C 3 2
I 3 2
C 1 5
I 4 5
I 2 4
C 3 5
I 1 3
C 1 5
S
SampleOutput2:
no
no
yes
yes
The network is connected.
Codes:
//#define LOCAL
#include <cstdio>
#include <cstdlib>
int findS(int *s, int v) {
while(s[v] >= 0) v = s[v];
return v;
}
void unionS(int *s, int c1, int c2) {
int r1 = findS(s, c1), r2 = findS(s, c2);
if(s[r1] < s[r2]) { s[r1] += s[r2]; s[r2] = r1; }
else { s[r2] += s[r1]; s[r1] = r2; }
}
int main()
{
#ifdef LOCAL
freopen("E:\\Temp\\input.txt", "r", stdin);
freopen("E:\\Temp\\output.txt", "w", stdout);
#endif
int i, n, c1, c2, cnt = 0; char c;
scanf("%d\n%c", &n, &c);
int *s = (int*)malloc(sizeof(int)*(n+1));
for(i=0; i<=n; ++i) s[i] = -1;
while(c != 'S') {
scanf("%d%d", &c1, &c2);
if(c == 'I') unionS(s, c1, c2);
else if(c == 'C') {
if(findS(s, c1) == findS(s, c2)) printf("yes\n");
else printf("no\n");
}
scanf("\n%c", &c);
}
for(i=1; i<=n; ++i) if(s[i] < 0) ++cnt;
if(cnt == 1) printf("The network is connected.\n");
else printf("There are %d components.\n", cnt);
free(s);
return 0;
}
05-树9:Huffman Codes.
Description:
In 1953, David A. Huffman published his paper "A Method for the Construction of Minimum-Redundancy Codes", and hence printed his name in the history of computer science. As a professor who gives the final exam problem on Huffman codes, I am encountering a big problem: the Huffman codes are NOT unique. For example, given a string "aaaxuaxz", we can observe that the frequencies of the characters 'a', 'x', 'u' and 'z' are 4, 2, 1 and 1, respectively. We may either encode the symbols as {'a'=0, 'x'=10, 'u'=110, 'z'=111}, or in another way as {'a'=1, 'x'=01, 'u'=001, 'z'=000}, both compress the string into 14 bits. Another set of code can be given as {'a'=0, 'x'=11, 'u'=100, 'z'=101}, but {'a'=0, 'x'=01, 'u'=011, 'z'=001} is NOT correct since "aaaxuaxz" and "aazuaxax" can both be decoded from the code 00001011001001. The students are submitting all kinds of codes, and I need a computer program to help me determine which ones are correct and which ones are not.
Input:
Each input file contains one test case. For each case, the first line gives an integer N (2, 63), then followed by a line that contains all the N distinct characters and their frequencies in the following format: c[1] f[1] c[2] f[2] ... c[N] f[N] where c[i] is a character chosen from {'0' - '9', 'a' - 'z', 'A' - 'Z', '_'}, and f[i] is the frequency of c[i] and is an integer no more than 1000. The next line gives a positive integer M (≤1000), then followed by M student submissions. Each student submission consists of N lines, each in the format: c[i] code[i] where c[i] is the i-th character and code[i] is an non-empty string of no more than 63 '0's and '1's.
Output:
For each test case, print in each line either "Yes" if the student's submission is correct, or "No" if not.
Note: The optimal solution is not necessarily generated by Huffman algorithm. Any prefix code with code length being optimal is considered correct.
SampleInput:
7
A 1 B 1 C 1 D 3 E 3 F 6 G 6
4
A 00000
B 00001
C 0001
D 001
E 01
F 10
G 11
A 01010
B 01011
C 0100
D 011
E 10
F 11
G 00
A 000
B 001
C 010
D 011
E 100
F 101
G 110
A 00000
B 00001
C 0001
D 001
E 00
F 10
G 11
SampleOutput:
Yes
Yes
No
No
Codes:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class HuffmanTree {
struct Node {
Node(int w = 0):weight(w), left(NULL), right(NULL), parent(NULL) {}
int weight; Node *left, *right, *parent;
};
class MinHeap {
public:
MinHeap(int N) {
cbtree = new Node*[N+1];
cbtree[0] = new Node(-1);
size = 0;
};
~MinHeap() {
delete cbtree[0];
cbtree[0] = NULL;
delete[] cbtree;
}
int Size() { return size; }
void Insert(Node *item) {
int i = ++size;
for (; item->weight<cbtree[i/2]->weight; i/=2) cbtree[i] = cbtree[i/2];
cbtree[i] = item; return;
}
Node* DeleteMin() {
Node *min_node = cbtree[1];
Node *last_node = cbtree[size];
cbtree[size--] = NULL;
int child, parant = 1;
while (parant*2 <= size) {
child = 2*parant;
if (child!=size && cbtree[child+1]->weight<cbtree[child]->weight) ++child;
if (last_node->weight < cbtree[child]->weight) break;
else cbtree[parant] = cbtree[child];
parant = child;
}
cbtree[parant] = last_node;
return min_node;
}
private:
Node* *cbtree; int size; };
public:
HuffmanTree(int capacity):heap(capacity), root(NULL), leaves(0), wpl(0) {}
~HuffmanTree() {
for (size_t i=0; i<nodes.size(); ++i) delete nodes[i];
}
void Insert(int item) {
++leaves;
nodes.push_back(new Node(item));
heap.Insert(nodes.back());
}
int GetWeight(int leave) { return nodes[leave]->weight; }
int GetWPL() {
if (!root) Build();
if (!wpl) {
for (int i=0; i<leaves; ++i) {
int depth = 0;
for (Node *leave=nodes[i]; leave->parent; leave=leave->parent) ++depth;
wpl += depth*nodes[i]->weight;
}
}
return wpl;
}
private:
Node *NextEmptyNode() {
static int next = leaves;
++next; nodes[next] = new Node();
return nodes[next];
}
void Build() {
if (!root) {
nodes.resize(2*leaves-1);
for (int i=0; i<leaves-1; ++i) {
Node *merged = NextEmptyNode();
merged->left = heap.DeleteMin();
merged->right = heap.DeleteMin();
merged->weight = merged->right->weight+merged->right->weight;
merged->right->parent = merged->left->parent = merged;
heap.Insert(merged);
}
root = heap.DeleteMin();
}
}
private:
MinHeap heap; Node *root;
int leaves, wpl;
vector<Node*> nodes;
};
bool IsPrefixConflict(string codes[], int N) {
for (size_t i=0; i<N; ++i) {
for (size_t j=0; j!=i &&j<N; ++j)
if(!codes[j].find(codes[i])) return true;
}
return false;
}
int main() {
int i, f, N, M; char c;
cin >> N;
HuffmanTree tree(N);
for (i=0; i<N; ++i) { cin >> c >> f; tree.Insert(f); }
cin >> M;
for (size_t mstu=0 ; mstu<M; ++mstu) {
string codes[64];
for (size_t ncode=0; ncode<N; ++ncode) cin >> c >> codes[ncode];
int wpl = 0;
for (int kcode=0; kcode<N; ++kcode) wpl += (codes[kcode].length()*tree.GetWeight(kcode));
if (!IsPrefixConflict(codes, N)&&wpl == tree.GetWPL()) cout << "Yes" << endl;
else cout << "No" << endl;
}
return 0;
}