目錄數組
樹結構仍是頗有意思的,由於之前老是要寫不少代碼,如今到了樹的結構,大多數都是直接用遞歸,代碼量少(個別題目除外)。其實最主要的就是二叉樹,不論是樹仍是森林,均可以轉換成二叉樹,在這個基礎上進行操做,其中印象最深的的就是目錄樹了,雖說操做起來有點麻煩,可是看到最終的結果仍是十分有成就感的。可是結合以前知識點的題目又有點力不足的感受,例如表達式樹,究其緣由應該是沒有複習的鍋了。樹在生活中仍是不少的,不只僅是方便查找和存儲數據,同時其中的哈夫曼樹又能夠用於數據的加密,涉及到一點密碼學的內容,真的是頗有意思了。函數
某學校有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:
一直卡在第一個問題,因此這個錯誤我也沒有去找,就是將兩個數和一個運算符合成一棵樹時忘記把運算符也出棧了。。
修改後: