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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

查找有向图中的环

發布時間:2024/9/30 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 查找有向图中的环 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

部分引自http://blog.csdn.net/xw13106209/article/details/6538634

有向圖:


主要有深度優先和拓撲排序2中方法

1、拓撲排序,如果能夠用拓撲排序完成對圖中所有節點的排序的話,就說明這個圖中沒有環,而如果不能完成,則說明有環。

2、可以用Strongly Connected Components來做,我們可以回憶一下強連通子圖的概念,就是說對于一個圖的某個子圖,該子圖中的任意u->v,必有v->u,則這是一個強連通子圖。這個限定正好是環的概念。所以我想,通過尋找圖的強連通子圖的方法應該可以找出一個圖中到底有沒有環、有幾個環。

3、就是用一個改進的DFS

??? 剛看到這個問題的時候,我想單純用DFS就可以解決問題了。但細想一下,是不能夠的。如果題目給出的是一個無向圖,那么OK,DFS是可以解決的。但無向圖得不出正確結果的。比如:A->B,A->C->B,我們用DFS來處理這個圖,我們會得出它有環,但其實沒有。

??? 我們可以對DFS稍加變化,來解決這個問題。解決的方法如下:

??? 圖中的一個節點,根據其C[N]的值,有三種狀態:

??? 0,此節點沒有被訪問過

??? -1,被訪問過至少1次,其后代節點正在被訪問中

??? 1,其后代節點都被訪問過。

??? 按照這樣的假設,當按照DFS進行搜索時,碰到一個節點時有三種可能:

??? 1、如果C[V]=0,這是一個新的節點,不做處理

??? 2、如果C[V]=-1,說明是在訪問該節點的后代的過程中訪問到該節點本身,則圖中有環。

??? 3、如果C[V]=1,類似于2的推導,沒有環。??? 在程序中加上一些特殊的處理,即可以找出圖中有幾個環,并記錄每個環的路徑


無向圖:

方法1:

  • 如果存在回路,則必存在一個子圖,是一個環路。環路中所有頂點的度>=2。??
  • n算法:??

    ???? 第一步:刪除所有度<=1的頂點及相關的邊,并將另外與這些邊相關的其它頂點的度減一。??

    ???? 第二步:將度數變為1的頂點排入隊列,并從該隊列中取出一個頂點重復步驟一。??

    ???? 如果最后還有未刪除頂點,則存在環,否則沒有環。??

  • n算法分析:??

    ???? 由于有m條邊,n個頂點。

    ?????i)如果m>=n,則根據圖論知識可直接判斷存在環路。(證明:如果沒有環路,則該圖必然是k棵樹 k>=1。根據樹的性質,邊的數目m = n-k。k>=1,所以:m<n)? ? ? ? ? ? ??

    ? ?? ii)如果m<n 則按照上面的算法每刪除一個度為0的頂點操作一次(最多n次),或每刪除一個度為1的頂點(同時刪一條邊)操作一次(最多m次)。這兩種操作的總數不會超過m+n。由于m<n,所以算法復雜度為O(n)。

  • 注:

    ?????該方法,算法復雜度不止O(V),首先初始時刻統計所有頂點的度的時候,復雜度為(V + E),即使在后來的循環中E>=V,這樣算法的復雜度也只能為O(V + E)。其次,在每次循環時,刪除度為1的頂點,那么就必須將與這個頂點相連的點的度減一,并且執行delete node from list[list[node]],這里查找的復雜度為list[list[node]]的長度,只有這樣才能保證當degree[i]=1時,list[i]里面只有一個點。這樣最差的復雜度就為O(EV)了。

    方法2:

    DFS搜索圖,圖中的邊只可能是樹邊或反向邊,一旦發現反向邊,則表明存在環。該算法的復雜度為O(V)。

    方法3:

    摘自:http://blog.csdn.net/lzrzhao/archive/2008/03/13/2175787.aspx

    PS:此方法于2011-6-12補充

    假定:圖頂點個數為M,邊條數為E

    遍歷一遍,判斷圖分為幾部分(假定為P部分,即圖有 P 個連通分量) 對于每一個連通分量,如果無環則只能是樹,即:邊數=結點數-1 只要有一個滿足 ?? ? 邊數 ? > ? 結點數-1
    原圖就有環
    將P個連通分量的不等式相加,就得到: P1:E1=M1-1 P2:E2=M2-1 ... PN:EN>MN-1 所有邊數(E) ? > ? 所有結點數(M) -?連通分量個數(P)
    即: ?E?+?P?>?M? 所以只要判斷結果??E? +?P?>?M?就表示原圖有環,否則無環.

    實例代碼如下:


    如果要將有向圖中的環輸出:

    bool Decoder::FindCycle(std::vector<vector<double> > &g, std::vector<int> &c) {int size = g.size();vector<int> color(size,0);//所有的結點都沒有被訪問。當i結點為0,未被訪問;i為-1,環;i為1,i的所有后裔結點都被訪問過//for (int i=0;i<size;++i)for (int i= size -1;i>=0;--i){if(color[i]==0){color[i] = -1;if(Dfs(g,color,c,i)){//c.push_back(i);return true;}}}return false; }bool Decoder::Dfs(std::vector<vector<double> > &g, std::vector<int> &color, std::vector<int> &c,int i)//如果有返回到i的環,則true;否則,false.遍歷結點i的所有后繼 {int size = g.size();for (int j=0;j<size;++j){if (g[i][j] !=noEdge){if(color[j]==0){color[j] = -1;if(Dfs(g,color,c,j)){//c.push_back(j);return true;}}else if(color[j] == -1){c.push_back(j);int start = j;for (int ind = 0;ind <size ;++ind)//復雜度太高了,應該記錄一個parent表{if(g[start][ind] !=noEdge && color[ind] == -1){if(ind == j)break;c.push_back(ind);start = ind;}}return true;}}}color[i] = 1;return false; }


    用拓撲排序查找有向圖的環有如下的缺點

    http://hi.baidu.com/hpc_robot/blog/item/c21ade979489d86855fb96f2.html

總結

以上是生活随笔為你收集整理的查找有向图中的环的全部內容,希望文章能夠幫你解決所遇到的問題。

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