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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

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

發布時間:2023/12/31 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 环的寻找:寻找无向图中所有存在的环-删除点法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

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

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

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


改進:

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

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

???????

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

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


一、使用刪除邊法

??????? 本例中,從頂點9開始,構建DFS

??????? 1.首先刪除所有度數為1的點,這樣點14就被刪除。這樣只剩下多度頂點的環

??????????


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

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

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

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

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


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

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

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

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


? ? 5.到了一個查找重復環的時候 ??

???????? 5.1. 此時沒有單度節點,

???????? 5.2. 出現問題,得重新考慮了!!!

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

???????

?? Code :

???

// 尋找聯通集合的閉包,判斷是否連通,返回閉包public static void findSub(Boolean adjM[][], Set<Integer> votex, ArrayList<Set<Integer>> loopSets) {if (votex.size() < 2) {// 治標不治本return;}for (int m = 0; m < adjM.length;++m){adjM[m][m] =false;}// 計算頂點的度Integer[] degrees = new Integer[adjM.length];degrees = calVotexDegree(adjM);//循環查找,找到所有的度不為1的閉包boolean isdeleted = true;while( isdeleted ){isdeleted = false;degrees = calVotexDegree(adjM);delete1Degree(adjM, degrees);// 刪除度數為1 的邊int l1 = votex.size();// 更新聯通集合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;//更新度,若被移除則相關的鄰接都置為falseadjM[m][i] = false;}}}int l2 = votex.size();if(l1!=l2) isdeleted = true;}// 遍歷所有節點,逐個取出,去除非環節點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);// 若已存在元素,則存在環,復制出環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;}
// 更新矩陣:刪除權值為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;}}}
輸出結果:輸出結果具有一定的概率性,和頂點的排序有關。



總結

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

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。