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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

Tarjan 算法详解

發布時間:2025/4/16 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Tarjan 算法详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一個神奇的算法,求最大連通分量用O(n)的時間復雜度,真實令人不可思議。轉自

廢話少說,先上題目

題目描述:

給出一個有向圖G,求G連通分量的個數和最大連通分量。

輸入:

n,m,表示G有n個點,m條邊

下面m行每行包含 x,y,表示有一條x到y的有向邊

輸出:

第一個數表示連通分量的個數,第二個數代表最大連通分量

輸入示例(如下圖)

6 8 1 2 1 4 2 3 2 5 3 6 4 5 5 1 5 6

輸入示例

4 3

很多人會想到DFS,但是時間復雜度為O(n^2),但是時間容易超限,所以我們要用到Tarjan

先理清一下概念:

連通分量:對于圖G來的一個子圖中,任意兩個點都可以彼此到達,這個子圖就被稱為圖G的連通分量(一個點就是最小的連通分量)

最大連通分量:對于圖G的一個子圖,這個子圖為圖G的連通分量,且是圖G所有連通分量中包含節點數最多的那個,即為G的最大聯通分量

時間戳:搜索時第幾個搜索到這個點。如搜索順序是1->2->3->6則6的時間截為4

下面就是tarjan的思路(第一次看不懂可以跳過,直接看詳細步驟,回來再看):

每個點都有兩個參數:low,dfn。dfn表示這個點的時間戳,而low代表這個點所能到達的最小的時間戳,開始low都等于dfn,但會經過不斷更新而減少。

從1節點進行深度優先搜索,途中用樹(一個轉化為棧的樹)維護。

當遇到一個點時,有如下判斷:

1、如果這個點沒有訪問過,就將這個點加入樹(棧)

2、如果這個點訪問過,且在樹(棧)里,與這個點的low比較,更新自己的low

返回時更新low

當一個點遍歷所有的邊后這個點的low還是等于dfn,將個點及以上出棧,這個點及棧以上的點構成一個連通分量。

來一點Chinese++(就是偽代碼)  

void tarjan(int 當前點) {這個點的low=dfn=時間戳;將這個點入棧;標記這個點入棧;枚舉這個點連接的所有邊{如果目標點沒有被訪問過{tarjan(目標點);更新當前點的low; } 如果目標點被訪問過&&在棧中{更新當前點的low; } }如果當前點的low==dfn{將這個點及棧以上的點出棧,標記成一個強連通分量; ans++; } }

詳細過程:

開啟黑暗之門

?

開始,從1節點開始,時間截和low都是1,將1入棧

stack:1,

走到2節點,2的時間戳dfn和low都是2,2入棧

stack:1,2

?

以此類推,將3、6入棧,時間戳分別為3、4

stack:1,2,3,6

?

此時,發現6節點遍歷了其所有出邊(本來就沒有)以后,它的low等于dfn,這就說明了6號節點沒有路徑能回到能到達它的節點,所以6就是一個單獨的連通分量,因此將6出棧,再回溯,此時在棧中比6(含)高的點都出棧,這些點構成一個連通分量(因為此時比6在棧頂,所以6是一個單獨的連通分量)ans++

stack:1,2,3

?

和剛才一樣,3節點的所有出邊已經遍歷一般,但low還是和dfn相等,所以3出棧,因為此時3在棧頂,所以3是一個單獨的連通分量。ans++

stack:1,2

?

再次遍歷從2遍歷到5,將5入棧,并且low和dfn都為5。

stack:1,2,5

然后5搜索到6,但是6不在棧里面,所以不管它

這是搜索到了1,發現1的時間戳1小于5的low,所以將5的low更新為1,。這時發現5沒有其他邊可以走了,所以返回

返回到2時,發現5的low比2的low小,所以更新2的low為1,繼續返回到1

再從1走到4,4的時間戳和low為6,將4入棧

stack:1,2,5,4  

從4走到5,發現5在棧中,且5的low比4的low小,所以4的low變成1,因為沒有邊再返回到1

此時,1的所有邊都走完啦,并且1的low等于dfn,所以把1及以上的節點出棧,構成連通分量,ans++

?繼續枚舉每一個點,如果這個點的時間戳為0(也就是沒有訪問過)tarjan(i);

現在貼上代碼,但是沒有完,我會對原理做詳細解釋:

void tarjan(int u) {in++;dfn[u]=in;low[u]=in;S.push(u);vis[u]=1;for(int e=head[u];e;e=next[e]){if(!dfn[to[e]]){tarjan(to[e]);low[u]=min(low[to[e]],low[u]);}else if(vis[to[e]])low[u]=min(low[u],dfn[to[e]]);}if(low[u]==dfn[u]){while(!S.empty() && S.top()!=u){vis[S.top()]=0;S.pop(); } vis[u]=0;S.pop();ans++;} }

演員表:

in:時間戳下標

dfn[i]:i節點的時間戳

low[i]:i所能到達的最小的時間戳

head[i],next[i],to[i]:鄰接表群演

vis[i]:i是否在棧里

S:棧

ans:計數

u:當前點

原理詳解:

1、其實雖說整個過程都在用棧維護,但是原理卻是一顆樹,比如當搜索到1、2、3、6時,樹是這樣的

你想象成樹就好,當我們確定6為一個單獨的連通分量的時候,把它咔嚓掉。現在6及以下的節點(這次沒有)成為一顆新的樹。


然后再用霜之哀傷砍掉3,3及以下節點(也是沒有)又變成了一個新的樹。

然后我們搜索到5,將5加入樹

然后再從1搜索到4,加入樹

然后返回到1,拔出1節點的霜之哀傷與耐奧祖融合,成為新的巫妖王。

總結

以上是生活随笔為你收集整理的Tarjan 算法详解的全部內容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 国产欧美一区二区三区在线看蜜臀 | 国产三级在线观看 | 亚洲自拍偷拍第一页 | 色久影院 | 九九综合九九 | 国产成人精品无码免费看81 | 国产一区在线观看视频 | 污污污污污污www网站免费 | 中文字幕av不卡 | 欧美日韩黄色一区二区 | 日韩三级成人 | 亚洲AV无码国产精品国产剧情 | 婷婷精品一区二区三区 | 五月婷婷综合色 | 一级黄色录像大片 | 欧美日日操 | 国产av 一区二区三区 | 四虎毛片| 国产传媒一级片 | 深田咏美中文字幕 | 国产成人免费电影 | 免费观看在线视频 | 亚洲免费观看av | 亚洲综合在线成人 | 福利小视频在线 | 午夜影视av | 少妇色| 韩国三级视频 | 日韩一级片免费看 | 日韩中文字幕在线免费观看 | 美女扒开尿口给男人看 | 99久热在线精品996热是什么 | 成人免费91| 国产手机在线视频 | 天天色天天搞 | 日本黄色一级视频 | 国产精品27p| 狠狠操天天操 | 成人福利在线免费观看 | 国产精品麻豆入口 | 6080亚洲精品一区二区 | 国产成人一区在线观看 | 中文字幕天堂 | 国产又黄又大又粗视频 | 亚洲涩视频 | 午夜伦理福利视频 | 久月婷婷 | 苍井空浴缸大战猛男120分钟 | 成人永久免费视频 | 免费观看久久 | 亲子乱aⅴ一区二区三区 | 草草草在线观看 | av爱爱| 亚洲美女精品 | 日韩一区二区三区精品 | 高清无码视频直接看 | 国产免费一区二区三区在线观看 | 国内视频一区二区三区 | 欧美精品一区二区三区久久久竹菊 | 1000部av| 在线观看超碰 | 免费久久一级欧美特大黄 | 美女脱了内裤喂我喝尿视频 | 日本美女视频网站 | 国产精品中文无码 | 亚洲欧美激情另类校园 | 99久久精品免费视频 | 一级黄色片网址 | 日韩少妇内射免费播放18禁裸乳 | 蜜桃在线一区 | 免费福利视频在线观看 | 亚洲av无码一区东京热久久 | 精品影视一区二区 | 西西毛片 | 欧美一级片黄色 | 97精品人人a片免费看 | 日韩电影在线一区 | 中文字幕视频网 | 肉大捧一进一出免费视频 | 日韩视频在线免费播放 | 欧美高清二区 | 亚洲区小说| 青娱乐激情 | 美女张开腿露出尿口 | 国产免费av网址 | 双性皇帝高h喷汁呻吟 | 在线观看黄网站 | 亚洲 欧美 日韩 综合 | 九九九网站 | 国产黄网在线观看 | 国产卡一卡二卡三 | 毛片无码免费无码播放 | 夜夜狠 | 欧美激情精品久久久久久蜜臀 | 国产色视频一区二区三区qq号 | 国产手机在线 | 成人在线视频免费看 | 91成人在线看 | 美女张开腿让男人桶爽 |