目錄面試
到了圖結構,數據結構更加體現出來它在生活中的實際應用,包括最小路徑尋找以及最小生成樹,所以他也顯得很重要,不只僅是在未來的工做或者工做面試,亦或者是acm的比賽中都須要大範圍的使用。其實在學習圖結構以前,我徹底不知道該怎麼存儲一個圖結構,樹還能想象,後來發現圖的存儲其實很簡單粗暴,可是也十分實用,對於不一樣的算法也都有不一樣的存儲結構,能夠說是很神奇了。然而這一章節的學習也須要花時間去理解,複習。算法
題目描述:數組
現有村落間道路的統計數據表中,列出了有可能建設成標準公路的若干條道路的成本,求使每一個村落都有公路連通所須要的最低成本。
輸入格式:
輸入數據包括城鎮數目正整數N(≤1000)和候選道路數目M(≤3N);隨後的M行對應M條道路,每行給出3個正整數,分別是該條道路直接連通的兩個城鎮的編號以及該道路改建的預算成本。爲簡單起見,城鎮從1到N編號。
輸出格式:
輸出村村通須要的最低成本。若是輸入數據不足以保證暢通,則輸出−1,表示須要建設更多公路。微信
自從上次梅梅在我面前秀過一手優先隊列我就對這個容器愛不釋手,配合優先隊列,我決定採用克魯斯卡爾算法再加以並查集的輔佐來完成這一個題目
在這以前要解決幾個問題:
1.首先是優先隊列中的比較問題,對於一個int型或者double型的變量進行操做固然容易,可對於一個結構體,如何傳入一個已有的函數讓他進行比較呢。這裏就須要在結構體中對比較符號進行重載,使得咱們能直接對結構體進行比較。
2.其次是優先隊列中的排序問題,優先隊列時默認從從大到小排列的,可是咱們這裏最小生成樹須要的是從小到大,因此咱們就須要在定義優先隊列的時候採用小頂堆進行排序。網絡
priority_queue<Road, vector<Road>, greater<Road>> all //首先定義一個all優先隊列 int count //計算已經存儲的道路 int cost //記錄消費 for i=1 to road: 將已有的道路信息傳入隊列; for i=0 to town: 初始化並查集 while all.size(): temp=all.front() all出隊 if(temp.town1和temp.town2不連通): Union(town1,town2)合併兩個村; cost更新; count++; 輸出cost
WA:這兩個錯誤的緣由其實都同樣,就是當不連通的時候沒有辦法判斷,之因此第一個錯誤多了兩分是由於我加了個if語句判斷M<N-1的狀況,後來我發現只要統計一下在操做過程當中鏈接上的道路數目是否是等於城鎮數減一就行了。數據結構
題目描述:函數
有了一張自駕旅遊路線圖,你會知道城市間的高速公路長度、以及該公路要收取的過路費。如今須要你寫一個程序,幫助前來諮詢的遊客找一條出發地和目的地之間的最短路徑。若是有若干條路徑都是最短的,那麼須要輸出最便宜的一條路徑。
輸入格式:
輸入說明:輸入數據的第1行給出4個正整數N、M、S、D,其中N(2≤N≤500)是城市的個數,順便假設城市的編號爲0~(N−1);M是高速公路的條數;S是出發地的城市編號;D是目的地的城市編號。隨後的M行中,每行給出一條高速公路的信息,分別是:城市一、城市二、高速公路長度、收費額,中間用空格分開,數字均爲整數且不超過500。輸入保證解的存在。
輸出格式:
在一行裏輸出路徑的長度和收費總額,數字間以空格分隔,輸出結尾不能有多餘空格。工具
思路一:這題我是用弗洛伊德算法去作的,心想日常的課後做業應該不會很難,因此時間複雜度高一點應該沒問題,本來的使用一個int矩陣去實現的,可是這裏多了一個價格的選項,因此咱們設計一個結構體來存儲這些數據學習
typedef struct road { int dist;//距離 int cost;//消費 }Road;
僞代碼以下:大數據
Road matrix[MAX] cin >> n >> m >> s >> d; 初始化矩陣全部元素爲INF while m--: 讀取路徑信息到矩陣 弗洛伊德算法 for k=0 to n-1: for i=0 to n-1: for j=0 to n-1: if matrix[i][j].dist > matrix[i][k]+matrix[k][j].dist: //原路徑比新路徑長 更新matrix[i][j]的cost和dist else if 原路徑等於新路徑: if 原路徑消費 > 新路徑: 更新matrix[i][j]的cost和dist else 保持不變 cout << matrix[s][d].dist << ' ' << matrix[s][d].cost;
思路二:Dijskstra算法
對於這個算法來說,只要在課本上算法的基礎上增長一個cost數組數組用來記錄消費就能夠了,而後最後進行修正的時候若是找到路程相等的就直接比較他們的消費就醒行了
思路一:
思路二:
WA:這裏錯誤是由於我忽略了他是一個無向圖,一開始當成有向圖作了,只要在初始化路徑信息時添加上面兩條語句就好啦。
題目描述:
「六度空間」理論又稱做「六度分隔(Six Degrees of Separation)」理論。這個理論能夠通俗地闡述爲:「你和任何一個陌生人之間所間隔的人不會超過六個,也就是說,最多經過五我的你就可以認識任何一個陌生人。」如圖1所示。
「六度空間」理論雖然獲得普遍的認同,而且正在獲得愈來愈多的應用。可是數十年來,試圖驗證這個理論始終是許多社會學家努力追求的目標。然而因爲歷史的緣由,這樣的研究具備太大的侷限性和困難。隨着當代人的聯絡主要依賴於電話、短信、微信以及因特網上即時通訊等工具,可以體現社交網絡關係的一手數據已經逐漸使得「六度空間」理論的驗證成爲可能。假如給你一個社交網絡圖,請你對每一個節點計算符合「六度空間」理論的結點佔結點總數的百分比。
輸入格式:
輸入第1行給出兩個正整數,分別表示社交網絡圖的結點數N(1<N≤104,表示人數)、邊數M(≤33×N,表示社交關係數)。隨後的M行對應M條邊,每行給出一對正整數,分別是該條邊直接連通的兩個結點的編號(節點從1到N編號)。
輸出格式:
對每一個結點輸出與該結點距離不超過6的結點數佔結點總數的百分比,精確到小數點後2位。每一個結節點輸出一行,格式爲「結點編號:(空格)百分比%」。
這道題目我想採用vector來作,vector至關於一個可增長的數組,這樣一來也就至關於在用鄰接表了
至於認識的人,我用set容器來存儲,由於set不會存儲重複數據,但其實直接用count來統計人數也行,我一開始是想六個層次無腦塞進set容器,這樣直接取size就能夠了,可是後來發現這樣會致使大數據內存爆掉
遍歷方式採用廣度遍歷,符合題意
main函數:
cin >> n >> e; set<int> check; vector<int> point[MAX]; while e--: 循環讀取人脈信息到point裏面 for i=1 to n: 初始化vis爲0 BFS(i, 0) 清空check
BFS函數:int i,int c;
queue<int> q; q.push(i) check.insert(i) for i=1 to 6: vector<int> store; 轉移q中的數據到store for i=0 to store.size()-1: int temp=store[i] 將temp的下一個節點所有入隊q
WA:這道題目是纏了我比較久的,我用vector去作,可是無論怎麼樣最後一個點老是內存超限,我真的超級納悶,照理說這個vector應該相似於鄰接表了,怎麼還會內存超限,我一開始代碼是這樣的
後來思索了很久
我將每一層的子元素入隊時沒有判斷是否曾經訪問過,直接所有入隊,難道時由於這個爆了???遂增長vis數組判斷是否訪問過
而後就過了
這幾題都沒作出來,就不貼錯題代碼了。。。我後面把這些題目又重作了一遍
題目1:最短路徑
修改後的代碼:
題目2:公路村村通
這道題目並不須要記錄上一個點的位置,就不用像書本同樣多一個數組了
修改後的代碼:
這詞上機考試,原想劍走偏鋒,不曾想被當場制裁,究其緣由,就是沒有好好去練習圖結構,對圖結構的一些算法也瞭解不是很清楚,仍是應該好好反思一下本身。