tarjan算法詳解

https://blog.csdn.net/jeryjeryjery/article/details/52829142?locationNum=4&fps=1

以防鏈接失效,特此轉載此博,如有侵權請見諒

?在有向圖G中,如果兩個頂點間至少存在一條路徑,稱兩個頂點強連通(strongly connected)。如果有向圖G的每兩個頂點都強連通,稱G是一個強連通圖。非強連通圖有向圖的極大強連通子圖,稱為強連通分量(strongly connected components)。如下圖中,強連通分量有:{1,2,3,4},{5},{6}

? ? ? ?Tarjan算法是基于對圖深度優先搜索的算法,每個強連通分量為搜索樹中的一棵子樹。搜索時,把當前搜索樹中未處理的節點加入一個堆棧,回溯時可以判斷棧頂到棧中的節點是否為一個強連通分量。Tarjan算法有點類似于基于后序的深度遍歷搜索和并查集的組合,充分利用回溯來解決問題。
在Tarjan算法中為每個節點i維護了以下幾個變量:
DFN[i]:深度優先搜索遍歷時節點i被搜索的次序。
low[i]:節點i能夠回溯到的最早位于棧中的節點。
flag[i]:標記幾點i是否在棧中。

Tarjan算法的運行過程:
(1).首先就是按照深度優先搜索算法搜索的次序對圖中所有的節點進行搜索。
(2).在搜索過程中,對于任意節點u和與其相連的節點v,根據節點v是否在棧中來進行不同的操作:
*節點v不在棧中,即節點v還沒有被訪問過,則繼續對v進行深度搜索。
*節點v已經在棧中,即已經被訪問過,則判斷節點v的DFN值和節點u的low值的大小來更新節點u的low值。如果節點v的?DFN值要小于節點u的low值,根據low值的定義(能夠回溯到的最早的已經在棧中的節點),我們需要用DFN值來更新u?的low值。
(3).在回溯過程中,對于任意節點u用其子節點v(其實不能算是子節點,只是在深度遍歷的過程中,v是在u之后緊挨著u的節點)的? ?low值來更新節點u的low值。因為節點v能夠回溯到的已經在棧中的節點,節點u也一定能夠回溯到。因為存在從u到v的直接路徑,所以v能夠到的節點u也一定能夠到。

(4).對于一個連通圖,我們很容易想到,在該連通圖中有且僅有一個節點u的DFN值和low值相等。該節點一定是在深度遍歷的過程中,該連通圖中第一個被訪問過的節點,因為它的DFN值和low值最小,不會被該連通圖中的其他節點所影響。

? ? ? 下面我們證明為什么僅有一個節點的DFN和low值相等。假設有兩個節點的DFN值和low值相等,由于這兩個節點的DFN值一定不相同?(DFN值的定義就是深度遍歷時被訪問的先后次序),所以兩個的low值也絕對不相等。由于位于同一個連通圖中,所以兩個節點必定相互可達,那么兩者的low值一定會被另外一個所影響(要看誰的low值更小),所以不可能存在兩對DFN值和low值相等的節點。

? ? ? ?所以我們在回溯的過程中就能夠通過判斷節點的low值和DFN值是否相等來判斷是否已經找到一個子連通圖。由于該連通圖中的DFN值和low值相等的節點是該連通圖中第一個被訪問到的節點,又根據棧的特性(先壓入? 棧的節點在棧的更里面),則該節點在最里面。所以能夠通過不停的彈棧,直到彈出該DFN值和low值相同的節點來彈出該連通圖中所有的節點。

?

Tarjan算法的C++實現代碼如下,可以配合上面的圖加以理解:

?

[cpp]?view plaincopy
    1. #include<iostream>??
    2. using?namespace?std;??
    3. int?DFN[105];??????????????????????????????????//記錄在做dfs時節點的搜索次序??
    4. int?low[105];??????????????????????????????????//記錄節點能夠找到的最先訪問的祖先的記號??
    5. int?count=1;???????????????????????????????????//標記訪問次序,時間戳??
    6. int?stack[105];????????????????????????????????//壓入棧中??
    7. int?top=-1;??
    8. int?flag[105];?????????????????????????????????//標記節點是否已經在棧中??
    9. int?number=0;??
    10. int?j;??
    11. int?matrix[105][105]={{0,1,1,0,0,0},{0,0,0,1,0,0},{0,0,0,1,1,0},{1,0,0,0,0,1},{0,0,0,0,0,1},{0,0,0,0,0,0}};??
    12. int?length;????????????????????????????????????//圖的長度??
    13. void?tarjan(int?u){??
    14. ????DFN[u]=low[u]=count++;?????????????????????//初始化兩個值,自己為能找到的最先訪問的祖先??
    15. ????stack[++top]=u;??
    16. ????flag[u]=1;?????????????????????????????????//標記為已經在棧中??
    17. ??
    18. ????for(int?v=0;v<length;v++){??
    19. ????if(matrix[u][v]){??
    20. ????????if(!DFN[v]){???????????????????????//如果點i沒有被訪問過??
    21. ????????tarjan(v);?????????????????????//遞歸訪問??
    22. ????????if(low[v]<low[u])??
    23. ????????????low[u]=low[v];?????????????//更新能找的到祖先??
    24. ????????}??
    25. ????????else{??????????????????????????????//如果訪問過了,并且該點的DFN更小,則??
    26. ????????if(DFN[v]<low[u]&&flag[v])?????//flag[v]這個判斷條件很重要,這樣可以避免已經確定在其他聯通圖的v,因為u到v的單向邊而影響到u的low??
    27. ????????low[u]=DFN[v];?????????????????//也就是已經確定了的聯通圖要剔除掉,剔除的辦法就是判斷其還在棧中,因為已經確定了的連通圖的點??
    28. ????????}??????????????????????????????????//flag在下面的do?while中已經設為0了(即已經從棧中剔除了)??
    29. ????}??
    30. ????}??
    31. ??
    32. ????//往后回溯的時候,如果發現DFN和low相同的節點,就可以把這個節點之后的節點全部彈棧,構成連通圖??
    33. ????if(DFN[u]==low[u]){??
    34. ????number++;???????????????????????????????//記錄連通圖的數量??
    35. ????do{??
    36. ????????j=stack[top--];?????????????????????//依次取出,直到u??
    37. ????????cout<<j<<"?";??
    38. ????????flag[j]=0;??????????????????????????//設置為不在棧中??
    39. ????}while(j!=u);??
    40. ????????cout<<endl;??
    41. ????}??
    42. }??
    43. int?main(){??
    44. ??????
    45. ????memset(DFN,0,sizeof(DFN));??????????????????//數據的初始化??
    46. ????memset(low,0,sizeof(low));??
    47. ????memset(flag,0,sizeof(flag));??
    48. ??????
    49. ????length=6;??
    50. ????tarjan(0);??
    51. ??
    52. ????cout<<endl;??
    53. ????for(int?i=0;i<6;i++){??
    54. ????cout<<"DFN["<<i<<"]:"<<DFN[i]<<"?low["<<i<<"]:"<<low[i]<<endl;??
    55. ????}??
    56. ????return?0;??
    57. } ?

轉載于:https://www.cnblogs.com/cglongge/p/8722202.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/280702.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/280702.shtml
英文地址,請注明出處:http://en.pswp.cn/news/280702.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Gitlab簡單使用CI/CD

開篇語大概是去年就想做這個事情了&#xff0c;奈何當時卡到一個docker命令找不到的問題上&#xff0c;導致文章難產了&#xff0c;墨跡了這么久&#xff0c;終于又有空來搗鼓它了。目的我們要實現的目的是我本地不斷提交代碼(CI),然后服務器不斷進行部署(CD)的一個簡單流程。準…

AppleScript: Handler

AppleScript絕對是個奇葩的存在&#xff01;不管功能有多強大。 Handler有兩種&#xff0c;一種是和OC類似的使用Label參數&#xff0c;一種是和javascript類似的使用括號把一堆參數都放在里面的。 label參數的Handler的寫法非常奇怪&#xff0c;光看文檔絕對讓人迷糊。這里按照…

powershell 運行策略

Unrestricted 這是一種比較寬容的策略&#xff0c;允許運行未簽名的腳本。對于從網絡上下載的腳本&#xff0c;在運行前會進行安全性提示&#xff1a; Set-ExecutionPolicy UnRestricted

免費的數字圖書館_不僅是書籍:您當地圖書館可能提供的所有免費數字資料

免費的數字圖書館You might think of libraries as old fashioned, or irrelevant in the age of the internet. You’d be wrong. 您可能會認為圖書館是老式的&#xff0c;或者與互聯網時代無關。 你會錯的。 Modern libraries offer books, yes, but they also provide inter…

iNeuOS工業互聯網操作系統,腳本化實現設備運行時長和效率計算與統計

目 錄1. 概述... 22. 實時采集開停狀態... 23. 增加虛擬設備... 24. 腳本統計和計算設備運行時長... 45. 設備運行時長報表... 71. 概述有一個煤礦項目&#xff0c;使用iNeuOS系統時有一個需要是&#xff1a;要統計設備的運行時長&#xff0c…

webpack二(以webpack4.x起步)

一.基本安裝首先我們要創建一個目錄&#xff0c;初始化npm&#xff0c;以及在本地安裝webpack&#xff1a;復制代碼mkdir webpackapp && cd webpackapp復制代碼npm init -y復制代碼npm install --save-dev webapck復制代碼現在我們看一下我們創建的目錄以及目錄下的結構…

阿里云中間件是什么-阿里云中間件介紹

阿里云中間件是什么?這其實是一個比較虛的概念。廣義的中間件范圍很廣。起溝通作用的都可以認為是中間件。甚至ODBC這樣的東西你也可以認為是中間件。 使用了中間件之后&#xff0c;以前直接連接的前臺應用程序和數據庫之前就多了個中間件&#xff0c;現在前臺程序把請求發給…

C# 圖片、文件等加入Project Resources

一、目的 1.編譯后&#xff0c;只想有一個exe文件&#xff0c;不想外部文件引用&#xff0c;直接運行exe文件即可。 2.不會出現文件丟失情況。 二、操作 1.右擊project ->properties->Resource&#xff0c;左上角選擇Image&#xff08;或其他類型&#xff09; 2. 點擊…

jfinal使用shiro注解大體流程

2019獨角獸企業重金招聘Python工程師標準>>> 上一篇答題梳理了jfinal整合shiro的流程&#xff0c;jfinal讀取shiro注解&#xff0c;這一篇將作為補充。 1.JFinalShiroPlugin作者為shiro的RequiresRoles&#xff0c;RequiresPermissions&#xff0c; RequiresAuthent…

chrome 快捷鍵取消_如何使用鍵盤快捷鍵在Chrome和Firefox中固定和取消固定選項卡...

chrome 快捷鍵取消If you tend to open a lot of tabs in your browser, it can become difficult to find the tabs with your most used websites. Pinning tabs in your browser moves those tabs to the left and shrinks the tabs to only show the favicon, and you can …

.NET Conf China 2022參會指南速覽(內含超多福利)趕緊預約!???

12月充滿驚喜各種美好節日紛至沓來似在獎勵一年辛苦勞作的你12月的第一波福利.NET Conf China 承包啦立即掃碼預約加入.NET年度盛宴搶12月第一波驚喜&#xff01;.NET Conf China 2022 .NET Conf China 2022是面向開發人員的社區峰會&#xff0c;延續 .NET Conf 2022 的活動&a…

python導入模塊--案例

1 導入模塊 1.1 問題 本案例要求先編寫一個star模塊&#xff0c;主要要求如下&#xff1a; 建立工作目錄 ~/bin/創建模塊文件 ~/bin/star.py模塊中創建pstar函數&#xff0c;實現打印50個星號的功能然后練習導入模塊&#xff0c;調用模塊中的函數&#xff1a; 在交互解釋器中導…

css常用命名

常用的CSS命名 頭&#xff1a;header 內容&#xff1a;content/container 尾&#xff1a;footer 導航&#xff1a;nav 側欄&#xff1a;sidebar 欄目&#xff1a;column 頁面外圍控制整體佈局寬度&#xff1a;wrapper 左右中&#xff1a;left right center 登錄條&#xff1a;l…

***關于WP的郵件無法發送問題的總結(原創)

1.用FTP打開 /wp-include/class-smtp.php &#xff0c;最好是下載下來&#xff0c;搜索一下&#xff0c;查找到如下的代碼&#xff1a; $this->smtp_conn stream_socket_client($host . ":" . $port,$errno,$errstr,$timeout,STREAM_CLIENT_CONNECT,$socket_cont…

C# 簡單方式運行powershell文件/使用cmd命令運行ps1

一、目的、構想 1.C# winfrom編譯的tool 運行一個powershell文件。 2.只需要運行即可&#xff0c;不需要返回值。 3.網上部分資料需要額外添加dll。 3.已經有cmd執行命令的函數&#xff0c;能否直接在cmd運行&#xff1f; 4.在cmd黑色窗口輸入powershell 能進入powershell…

?.Net 7 AOT 徹底解析下(完結篇)

楔子&#xff1a;本篇是承繼前面三篇文章而來&#xff0c;分別為&#xff1a;.Net 7 的 AOT 和 CLR有什么區別&#xff1f;.Net 7 的 R2R,Crossgen2是什么?.Net 7 的AOT原理簡析通過以上三篇的基礎&#xff0c;本篇來徹底解析下AOT這門技術的底層原理。AOT此終&#xff0c;不再…

cmd暫停快捷鍵_是否有鍵盤快捷鍵可以暫停正在運行的CMD窗口的輸出?

cmd暫停快捷鍵When running a batch script, you may need or want to pause the output in the CMD window so that you can look things over. Is there an easy way to pause, then restart the output? Today’s SuperUser Q&A post has the answer to help with a re…

bash快捷鍵

Ctrl h &#xff1a;回退一個字符Ctrl f &#xff1a;光標前進一個字符Ctrl b &#xff1a;光標后退一個字符Ctrl w &#xff1a;刪除光標之前的一個字符串&#xff08;進入剪切板&#xff09;Ctrl u &#xff1a;刪除光標前的所有字符 &#xff08;進入剪切板&#xff09…

J - 青蛙的約會(擴展歐幾里得)

https://vjudge.net/contest/218366#problem/J 第一步追及公式要寫對&#xff1a;ynk-(xmk)pL > (n-m)klpx-y 可以看出擴展歐幾里得原型&#xff0c;這里注意擴展歐幾里得求出的是任意解&#xff0c;非最優&#xff0c;要推出最小解k。 (n-m)xlygcd > (n-m)(x*(x-y)/gcd)…

C# 簡單方式解壓Zip文件/使用VS2019自帶功能

一、目的、構想 1.直接解壓zip文檔。 2.網上資料不少需要外部dll。 3. 找到可以不需要外部dll方法&#xff0c;分享。 二、code實現 using System.IO.Compression;string filePath "c:\Server\fileList"; string zipPath "C:\Server\Download\Auto.zip&quo…