日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

环的寻找:寻找无向图中所有存在的环-删除点法

發(fā)布時間:2023/12/1 综合教程 45 生活家
生活随笔 收集整理的這篇文章主要介紹了 环的寻找:寻找无向图中所有存在的环-删除点法 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

??????? 此文討論一個無向圖中存在環(huán)的問題,在不管多復(fù)雜的連通圖中尋找出所有的環(huán),使用刪除點的方法。

??????? 此外,這個版本的查找方法可以用于其他場景:找出無向圖中所有的環(huán)的算法?????????????

??????? 結(jié)果能找到最小的環(huán),或許要靠運氣,輸出該輸出的環(huán)...............,這是原始算法。

改進(jìn):

可以輸出最大環(huán)(通過跳過多度點),可以輸出最小子環(huán)(通過使用最短路徑)......................

??????? 使用一個圖:

???????

??????? 比如在上圖中,存在多個環(huán)(1,2,3,4,5,6)(6,7,8,9)(1,2,5,6)(1,2,3,5,6).........

??????? 怎么尋找呢?

一、使用刪除邊法

??????? 本例中,從頂點9開始,構(gòu)建DFS

??????? 1.首先刪除所有度數(shù)為1的點,這樣點14就被刪除。這樣只剩下多度頂點的環(huán)

??????????

??????? 2. 若從頂點9開始,找到了環(huán)(9,8,6,7),對于頂點8和頂點7,其所有鏈接的邊都在當(dāng)前環(huán)上,則可以刪除掉兩個頂點;

???????? 而9除了處于環(huán)中的邊,還有其他邊,則不能刪除。此外,頂點6也不能刪除。

???????? 判斷條件: 若頂點X鏈接的邊在這一個環(huán)上,則可以刪除此頂點。

???????? ????

???????????????? 例如:在圖中,刪除的點為7和8,同時所有的鏈接邊也刪除。輸出環(huán)(9.8.7.6)。

??????? 3. 使用堆棧,再次查找10,可以輸出環(huán)(10,11,12,13),同時可以刪除頂點(11,12,13)。此時頂點10 的度置位1,標(biāo)識為已遍歷狀態(tài)。

???????? ???????

??????? 4.每次查找環(huán),都刪除度為1的節(jié)點和連接邊。此時可以刪除10,9,樹退化為一顆子樹。

?????????????????

? ? 5.到了一個查找重復(fù)環(huán)的時候 ??

???????? 5.1. 此時沒有單度節(jié)點,

???????? 5.2. 出現(xiàn)問題,得重新考慮了!!!

??????? 從頂點6開始找到所有的環(huán):注意此過程依然為生成樹的過程,每一個邊都被設(shè)定為有向邊。

???????

?? Code :

???

	// 尋找聯(lián)通集合的閉包,判斷是否連通,返回閉包public static void findSub(Boolean adjM[][], Set<Integer> votex, ArrayList<Set<Integer>> loopSets) {if (votex.size() < 2) {// 治標(biāo)不治本return;}for (int m = 0; m < adjM.length;++m){adjM[m][m] =false;}// 計算頂點的度Integer[] degrees = new Integer[adjM.length];degrees = calVotexDegree(adjM);//循環(huán)查找,找到所有的度不為1的閉包boolean isdeleted = true;while( isdeleted ){isdeleted = false;degrees = calVotexDegree(adjM);delete1Degree(adjM, degrees);// 刪除度數(shù)為1 的邊int l1 = votex.size();// 更新聯(lián)通集合for (int i = 0; i < degrees.length; ++i) {if (degrees[i] == 0) {votex.remove(i);for (int m = 0; m < adjM.length;++m){adjM[i][m] = false;//更新度,若被移除則相關(guān)的鄰接都置為falseadjM[m][i] = false;}}}int l2 = votex.size();if(l1!=l2) isdeleted = true;}// 遍歷所有節(jié)點,逐個取出,去除非環(huán)節(jié)點Set<Integer> loop = new HashSet<Integer>();Set<Integer> sub = new HashSet<Integer>();boolean isBlankX = false;boolean isFind = false;for (int ob : votex) {int obj = ob;sub.add(obj);int idx = obj;for (int j = idx; j < adjM[idx].length;) {if (adjM[idx][j]) {if (sub.contains(j) && idx != j) {transSet(sub, loop);// 若已存在元素,則存在環(huán),復(fù)制出環(huán)loopSets.add(loop);votex.removeAll(loop);sub.clear();findSub(adjM, votex, loopSets);isFind = true;if (votex.size() < 3) {// 剩余兩個就不再尋找isBlankX = true;}++j;} else {sub.add(j);++j;}} else++j;}if (isFind)break;}return;}

// 輸出頂點的度public static Integer[] calVotexDegree(Boolean adjM[][]) {Integer[] degrees = new Integer[adjM.length];for (int i = 0; i < adjM.length; ++i) {degrees[i] = 0;for (int j = 0; j < adjM[i].length; ++j) {if (adjM[i][j] == true) {degrees[i] = degrees[i] + 1;}}}return degrees;}

// 更新矩陣:刪除權(quán)值為1和0的邊public static void delete1Degree(Boolean[][] adjM, Integer[] degrees) {for (int j = 0; j < adjM.length; ++j) {adjM[j][j] = false;// 自身邊消除掉if (degrees[j] < 2) {for (int k = 0; k < adjM[j].length; ++k) {adjM[j][k] = false;adjM[k][j] = false;}degrees[j] = 0;}}}

輸出結(jié)果:輸出結(jié)果具有一定的概率性,和頂點的排序有關(guān)。

總結(jié)

以上是生活随笔為你收集整理的环的寻找:寻找无向图中所有存在的环-删除点法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。