目录数组
树结构仍是颇有意思的,由于之前老是要写不少代码,如今到了树的结构,大多数都是直接用递归,代码量少(个别题目除外)。其实最主要的就是二叉树,不论是树仍是森林,均可以转换成二叉树,在这个基础上进行操做,其中印象最深的的就是目录树了,虽说操做起来有点麻烦,可是看到最终的结果仍是十分有成就感的。可是结合以前知识点的题目又有点力不足的感受,例如表达式树,究其缘由应该是没有复习的锅了。树在生活中仍是不少的,不只仅是方便查找和存储数据,同时其中的哈夫曼树又能够用于数据的加密,涉及到一点密码学的内容,真的是颇有意思了。函数
某学校有N个学生,造成M个俱乐部。每一个俱乐部里的学生有着必定类似的兴趣爱好,造成一个朋友圈。一个学生能够同时属于若干个不一样的俱乐部。根据“个人朋友的朋友也是个人朋友”这个推论能够得出,若是A和B是朋友,且B和C是朋友,则A和C也是朋友。请编写程序计算最大朋友圈中有多少人。学习
输入格式:测试
输入的第一行包含两个正整数N(≤30000)和M(≤1000),分别表明学校的学生总数和俱乐部的个数。后面的M行每行按如下格式给出1个俱乐部的信息,其中学生从1~N编号:第i个俱乐部的人数Mi(空格)学生1(空格)学生2 … 学生Mi加密
输出格式:设计
输出给出一个整数,表示在最大朋友圈中有多少人。code
//对于每一个朋友圈,咱们设立一个boss,表明这个朋友圈的头头 //而且设立一个全局数组用来存储每一个人对应的boss信息 //咱们想获得的结果是朋友圈中全部人的boss是同一我的 全局变量:circle数组//用于存储boss信息 find函数:int x //这是传参,下同,函数功能是查找x的boss 查找x在circle中的boss,若是x自己就是一个boss,返回x; 若是不是,继续递归find(circle[x]),一级一级地找x的最终boss,并将boss的值返回,赋予circle[x] //将返回的boss的值赋予circle[x]很重要,由于全部圈中的boss可能合并致使boss改变 返回x的boss unit函数:int person1,int person2//功能:联合person1和person2所在的朋友圈 find函数查找person1的boss find函数查找person2的boss 若是两人的boss不相同,就让person2的boss作person1的boss的小弟 //也就是令person2的boss在数组中对应的值为person1的boss main函数: cin >> m,n 根据m对circle数组初始化 while(n--)//读入朋友圈 读取第一我的bigBoss做为这个朋友圈的boss 读入剩下的全部人,并用unit函数将他们联合为一个朋友圈 //在未联合以前,每一个人都是本身的boss static int result[]//统计每一个boss小弟人数 int max = 0//最大值 for i = 1 to m: int b = i 的boss result[b]++ if result[b] > max: max=result cout << max
题外话:其实这道题我在树的PTA里面是没有写的,由于我觉得考试后题组还会开放。。就只记了思路,并未实践
。不过我在固定题目集里面找到了这道题,并用下面的代码成功经过。blog
WA:第一次提交出错是由于我在unit函数中令person2的boss等于person1,而未对二者的boss进行操做。致使这两个小弟谜之叛变。。。。排序
这道题目其实就是个阉割版的哈夫曼树生成,由于你不须要最后的树结构,因此这道题目其实能够只用一个数组解决递归
main函数: int wood数组 for i = 1 to n: 读入每根木头的长度 sort函数对wood数组进行快速排序//毕竟C++有,就直接用了。否则冒泡半天 for i = 0 to n-2: 将wood[i]和wood[i+1]相加获得和plus sum += plus //sum为总消费 将和按照升序插入到后面的数组中//本想着这里也用sort可是后面实验了发现会超时 cout << sum
人类学研究对于家族很感兴趣,因而研究人员搜集了一些家族的家谱进行研究。实验中,使用计算机处理家谱。为了实现这个目的,研究人员将家谱转换为文本文件。下面为家谱文本文件的实例:
John Robert Frank Andrew Nancy David
家谱文本文件中,每一行包含一我的的名字。第一行中的名字是这个家族最先的祖先。家谱仅包含最先祖先的后代,而他们的丈夫或妻子不出如今家谱中。每一个人的子女比父母多缩进2个空格。以上述家谱文本文件为例,John这个家族最先的祖先,他有两个子女Robert和Nancy,Robert有两个子女Frank和Andrew,Nancy只有一个子女David。在实验中,研究人员还收集了家庭文件,并提取了家谱中有关两我的关系的陈述语句。下面为家谱中关系的陈述语句实例:
John is the parent of Robert Robert is a sibling of Nancy David is a descendant of Robert
研究人员须要判断每一个陈述语句是真仍是假,请编写程序帮助研究人员判断。
输入格式:
输入首先给出2个正整数N(2≤N≤100)和M(≤100),其中N为家谱中名字的数量,M为家谱中陈述语句的数量,输入的每行不超过70个字符。名字的字符串由不超过10个英文字母组成。在家谱中的第一行给出的名字前没有缩进空格。家谱中的其余名字至少缩进2个空格,即他们是家谱中最先祖先(第一行给出的名字)的后代,且若是家谱中一个名字前缩进k个空格,则下一行中名字至多缩进k+2个空格。在一个家谱中一样的名字不会出现两次,且家谱中没有出现的名字不会出如今陈述语句中。每句陈述语句格式以下,其中X和Y为家谱中的不一样名字:
X is a child of Y X is the parent of Y X is a sibling of Y X is a descendant of Y X is an ancestor of Y
输出格式:
对于测试用例中的每句陈述语句,在一行中输出True,若是陈述为真,或False,若是陈述为假。
这题一样也是在固定题目集过的
cin不能读入空格,因此这里得用getline,还有就是存储在map的时候是不能带空格的,而后string没有trim这样的去空格函数,因此就只好本身写一个
//读取人物关系信息 map<string, string> relation stack<string> family while(1) 读取一我的名name if 空栈: 直接入栈 continue if 栈顶是 name的父亲: relation[name] = 栈顶//创建关系 入栈name else 不断退栈直到栈顶是name的父亲 relation[name] = 栈顶 入栈name
//解决输入的问题,采用递归 solve函数:string name1,name2,re//re是关系 switch(re[0]) case c:判断name2是不是name1的父亲,返回判断结果//判断是否是儿子 case p:同上//判断是否是父母 case s:同上//判断是否是兄弟 case a:GrandSearch(name1,name2,re)//判断是否是祖先 case d:GrandSearch(name2,name1,re)//判断是否是祖孙 GrandSearch函数: if name1是惟一的祖先: return false if name1的父亲是name2: return true else return GrandSearch(name1的父亲,name2)//递归函数很差讲,,就是不断找name1的父亲,直到找不到或者name1的父亲就是name2为止
WA:之因此一直过不去是由于我觉得每一行的空格与下一行的空格相差只有2,0,-2,因此没有用if包括进去,其实不止,还多是任何负偶数,以下面的David和上一行的Nancy就差了6,修改一下if语句的条件就好辣
John Robert Frank Andrew Nancy David
此次省赛ACM恰好遇到一题有关树的题目,能够拿出来看看
It is known that there are N cats in Quasrain's home. The weight of cat i is A[i]. As Quasrain is evil, he wants to do something to the cats.
Practicing for two years and a half, the cats have gotten the commands of Quasrain. Whenever Quasrain say a a color, the cats in the actual color would come out, and Quasrain would cost sum of their weight. For example, now Quasrain has three cats in red, weights of {1,2,3}, and two cats in green, weights of {7,8} .If he says red, he would cost 6 (green for 15). Then he would choose some of them, would never stop until there isn't any pair of cats with the same color.
Initially, the cats are all in color white. Quasrain want to know, how much he wanld cost at least.
The first line is a number N(2<=N<=10^5)
Then one line with N numbers, A[i] for the weight of cats i.(1<=A[i]<=10^9)
Only one number, representing the least cost of Quasrain.
Input:
4
6 7 70 25
Output:
159
起初我研究了一下样例,觉得是每次叫一个最多数量颜色的猫,而后给里面其中一只上色,循环这个过程获得的最终答案,可是后面代码实现后提交上去是个WA。通过小组队员的一番bug测试,最终肯定这是一道哈夫曼树类型题。并决定采用优先队列来解决。
将全部的猫的weight所有放进一个使用小顶堆的优先队列q; int sum=0; while(q.size()!=1) 出队权值最小的两项并求和plus; 入队plus; sum+=plus; 输出sum;
这道题其实一开始真的没看出来是哈夫曼树的题目,可是后面根据队友找的的一组数据,就是四只100的猫要进行操做的时候,发现应该先把四只全叫出来涂色两只,而后就获得了两种颜色各有两只的猫,这时只要每种颜色叫一次而后涂色一只就能够达到最低消费。如今想起来这种题目更像是哈夫曼树生成的逆过程,哈夫曼树一开始不是要选择最小的两个嘛,是从叶子节点开始,合并生成根节点的过程。而叫猫一开始是要所有叫出来,而后分解为一只只不一样颜色的猫的过程。过程相反,实现则相同,之后遇到这类题目均可以考虑采用优先队列来解决。
果真表达式树仍是没掌握好啊
问题1:
讲真的我也不知道本身怎么写出这东西来的,我当时就坐在那眼睁睁看着给t->data赋值‘1’,结果t->data里面的数据变成’?‘,而后内心充满了'?????????????'
问题2:
一直卡在第一个问题,因此这个错误我也没有去找,就是将两个数和一个运算符合成一棵树时忘记把运算符也出栈了。。
修改后: