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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

tarjan算法不是很懂先mark一下。

發布時間:2023/11/27 生活经验 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 tarjan算法不是很懂先mark一下。 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
?前面為轉載的。后面是自己的理解。

三種tarjan算法(上)

。這篇算是做一個總結吧。
  1. 求強連通分量
  2. 求無向圖的割和橋
  3. 最近公共祖先


求強連通分量


?基本概念:

? ? ? 強連通是有向圖才有的概念。一個有向圖是強連通的是對于每個有序對 u,v,存在一條從 u到v ?的路徑。一個有向圖的強連通分量是指它的極大連通子圖。就是你可以從 a地走到 b 地,同樣可以從b地走到a地,a,b就是連通的。 ? ? ? 下圖(圖片來自這里)中 頂點 {1,2,3,4}是一個強連通分量,因為它們兩兩都可以到達。直觀上來講,所謂的強連通,(如果有至少有一個頂點)就是可以至少形成一個環。如1->3->4->1就是一個環,它們就是強連通的。注意也有像{5},{6}這樣的的連通分量。




? ? ??強連通的tarjan 算法是基于圖的深度優先搜索(這個經常用于獲取圖的各種信息)。下面說一下幾個約定:?
  1. 時間戳 ? ? ? :DFN[i]是指結點i被遍歷的時間。
  2. Low[i] ? ? ? :是指在搜索樹中,結點i和其子孫可以訪問到的最早的祖先,Low[i] = Min(DFN[i], DFN[j], Low[k])其中j是i的祖先(我們把子孫連到祖先的邊叫后向邊),k是i 的子女。
  3. 結點的顏色color[i]是用于標示結點i的狀態:白色指還沒到搜索到,灰色正在被搜索,黑色處理完畢。在實際操作中用-1,0,1分別代表白色、灰色、黑色

? ? ? tarjan算法的步驟:? ? ?

  1. 先把所有的結點的顏色都初始化白色,并把棧清空。
  2. 找到一個白色的結點i(即結點的顏色為白色)
  3. 給結點一個時間戳,把結點圧入棧中,并把結點標記為灰色。令Low[i] = DFN[i]?
  4. 遍歷結點i 的每條邊(i,j)。若color[j]是白色,就對結點i重復2~5步驟。并令Low[i] = min(Low[j],low[i]).如果color[j]是灰色,令Low[i] = min(Low[i],DFN[j])。如果是黑色不做任何處理。
  5. 把結點的顏色改為黑色,如果Low[i] = DFN[i],就把從棧頂到結點i間的元素彈出
  6. 重復步驟2,至到沒有白色頂點

? ? ? 下面是算法的一個模板:

[cpp]?view plaincopy
  1. <pre?name="code"?class="cpp">#include?<math.h>??
  2. #include?<stdio.h>??
  3. #include?<string.h>??
  4. #include?<stdlib.h>??
  5. ??
  6. //從頂點0開始??
  7. //?要用的話要初始化:調用Adj.initial?和?tarjan.initial??
  8. //要解決問題用調用tarjan.solve??
  9. //對tarjan.initial要傳入的參數是圖邊集Adj,和頂點個數n??
  10. ??
  11. const?int?maxn?=?11000;??
  12. //頂點的規模??
  13. const?int?maxm?=?210000;??
  14. //邊的規模,如果是無向圖要記得乘以2??
  15. ??
  16. const?int?GRAY?=?0;??
  17. const?int?WHITE?=-1;??
  18. const?int?BLACK?=?1;??
  19. ??
  20. typedef?struct?Edge{??
  21. ????int?s;??
  22. ????int?e;??
  23. ????int?next;??
  24. }Edge;??
  25. ??
  26. typedef?struct?Adj{??
  27. ????int?edge_sum;??
  28. ????int?head[maxn];??
  29. ????Edge?edge[maxm];??
  30. ??
  31. ????void?initial(){???
  32. ????????edge_sum?=?0;??
  33. ????????memset(head,-1,sizeof(head));??
  34. ????}??
  35. ??
  36. ????void?add_edge(int?a,?int?b){??
  37. ????????edge[edge_sum].s?=?a;??
  38. ????????edge[edge_sum].e?=?b;??
  39. ????????edge[edge_sum].next?=?head[a];??
  40. ????????head[a]?=?edge_sum++;??
  41. ????}??
  42. }Adj;??
  43. ??
  44. typedef?struct?Tanjan{??
  45. ????int?n;??
  46. ????int?*head;??
  47. ????Adj?*adj;??
  48. ????Edge?*edge;??
  49. ??
  50. ????int?cnt;??
  51. ????int?top;??
  52. ????int?cur;??
  53. ??
  54. ????int?dfn[maxn];??
  55. ????int?low[maxn];??
  56. ????int?color[maxn];??
  57. ????int?stack[maxn];??
  58. ????int?belong[maxn];??
  59. ??
  60. ????void?initial(Adj?*_adj,int?_n){??
  61. ????????n?=?_n;??
  62. ????????adj?=?_adj;??
  63. ????????head?=?(*adj).head;??
  64. ????????edge?=?(*adj).edge;??
  65. ????}??
  66. ??
  67. ????void?solve(){??
  68. ????????memset(dfn,-1,sizeof(dfn));??
  69. ????????memset(color,WHITE,sizeof(color));??
  70. ??
  71. ????????top?=?cnt?=?cur?=?0;??
  72. ????????for(int?i?=?0;?i?<?n;?i++)??
  73. ????????????if(color[i]?==?WHITE)//找到一個白色的頂點,就開始處理??
  74. ????????????????tarjan(i);??
  75. ????}??
  76. ??
  77. ????inline?int?min(int?a,?int?b){??
  78. ????????if(a?<?b)?return?a;??
  79. ????????else?return?b;??
  80. ????}??
  81. ??
  82. ????void?tarjan(int?i){??
  83. ????????int?j?=?head[i];??
  84. ??
  85. ????????color[i]?=?GRAY;//標記為灰色??
  86. ????????stack[top++]?=?i;//把結點圧入棧頂??
  87. ??
  88. ????????dfn[i]?=?low[i]?=?++cur;//給結點一個時間戳,并給Low初始化??
  89. ??
  90. ????????while(j?!=?-1){??
  91. ????????????int?u?=?edge[j].e;??
  92. ????????????if????????(dfn[u]?==?WHITE){??
  93. ????????????????tarjan(u);??
  94. ????????????????low[i]?=?min(low[i],low[u]);??
  95. ????????????//更新low???
  96. ????????????}else??if?(color[u]?==?GRAY)??
  97. ????????????????low[i]?=?min(low[i],dfn[u]);??
  98. ????????????//一條后向邊??
  99. ????????????j?=?edge[j].next;??
  100. ????????}??
  101. ??
  102. ????????color[i]?=?BLACK;??
  103. ????????if(low[i]?==?dfn[i]){??
  104. ????????????do{??
  105. ????????????????j?=?stack[--top];??
  106. ????????????????belong[j]?=?cnt;??
  107. ????????????}while(i?!=?j);??
  108. ????????????++cnt;????
  109. ????????}??
  110. ????}??
  111. }Tarjan;??
  112. ??
  113. Adj?adj;??
  114. Tarjan?tj;</pre><br>??
  115. <br>??
  116. <pre></pre>??
  117. <pre></pre>??
  118. <pre></pre>??
  119. <pre></pre>??
  120. <pre></pre>??

tarjan算法的簡單證明:

? ? ? ? ?首先,這邊再重復一下什么是后向邊:就是在深度優先搜索中,子孫指向祖先的邊。在一棵深度優先搜索樹中,對于結點v, 和其父親結點u而言,u,v 屬于同一個強連通分支的充分必要條件是 ?以v為根的子樹中,有一條后向邊指向u或者u的祖先。
1 、必要性。 ? ? ? ? ? ? ?如果 u,v屬于同一個強連通分支則必定存在一條 u到 v的路徑和一條v到u的路徑。合并兩條則有 u->v->v1->v2->..vn->u, 若頂點v1到vn都是v 的子孫,則有 vn->u這樣一條后向邊。 ? ? ? ? ? 如果v1到vn 不全是vn的子孫,則必定有一個是u的祖先,我們不妨設vi為u的祖先,則有一條后向邊 V[i-1] ->v[i]。
2.、充分性。 ? ?我們設 u1->u2->u3..->un->u->v->v1->v2..->vn,我們假設后向邊vn指向ui則有這樣一個環:u[i]->u[i+1]...->u->v->v1->v2..->v[n-1]->v[n]->u[i],易知,有一條u->v的路徑,同時有v->u的路徑。固u,v屬于同一連通分支。
? ? ? ? 在算法開始的時候,我們把i圧入棧中。根據low[i] 和 dfn[i]的定義我們知道, ? ? ? ? 如果low[i] < dfn[i] 則以i為頂點的子樹中,有指向祖先的后向邊,則說明i和i的父親為在同一連通分支,也就是說留在棧中的元素都是和父結點在同一連通分支的 ? ? ? ? ?如果low[i] == dfn[i],則?i為頂點的子樹中沒有后向邊,那么由于 ?留在棧中的元素都是和父結點在同一連通分支的,我們可以知道,從棧頂到元素i構成了一個連通分支。顯然,low[i]不可能小于dfn[i]。 __________________________________________________________________________________________________----我的理解,感覺有點類似于并查集,一開始假設有n個連通分量既dfn,low是我們進行判斷后修正的既low[n]=m表示實際上n這點屬于m這個連通分量,個點屬于哪個連通分量。然后進行深搜當找到一個環既(Instack[j]==true)這次找到的點是我們之前搜索到的,那這個點就屬于dfn[j]這個連通分量。
#define M 5010//題目中可能的最大點數
int STACK[M],top=0;//Tarjan算法中的棧
bool InStack[M];//檢查是否在棧中
int DFN[M];//深度優先搜索訪問次序int Low[M];//能追溯到的最早的次序
int ComponentNumber=0;//有向圖強連通分量個數
int Index=0;//索引號
vector<int> Edge[M];//鄰接表表示
vector<int> Component[M];//獲得強連通分量結果
int InComponent[M];//記錄每個點在第幾號強連通分量里
int ComponentDegree[M];//記錄每個強連通分量的度void Tarjan(int i)
{int j;DFN[i]=Low[i]=Index++;InStack[i]=true;STACK[++top]=i;for (int e=0;e<Edge[i].size();e++){j=Edge[i][e];if (DFN[j]==-1){Tarjan(j);Low[i]=min(Low[i],Low[j]);}elseif (InStack[j]) Low[i]=min(Low[i],DFN[j]);}if (DFN[i]==Low[i]){ComponentNumber++;do{j=STACK[top--];InStack[j]=false;Component[ComponentNumber].push_back(j);InComponent[j]=ComponentNumber;}while (j!=i);}
}





總結

以上是生活随笔為你收集整理的tarjan算法不是很懂先mark一下。的全部內容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 日本午夜免费福利视频 | 一级免费视频 | 在线观看第一页 | 欧美中文字幕一区二区三区 | 国产九色在线播放九色 | 成人激情免费 | 欧美sm视频 | a级淫片 | 神马午夜激情 | av一区二区免费 | 精品电影在线观看 | aaa级黄色片 | 国产精品久久久久久妇女6080 | 久久艹在线观看 | 欧美电影一区二区三区 | 国产美女无遮挡免费 | 黄色二级视频 | 少妇中文字幕 | 日本黄页网站 | 亚洲涩视频 | 嫩草嫩草嫩草嫩草嫩草 | 亚洲好视频| 日韩av在线第一页 | 久久永久免费 | 亚洲欧美在线不卡 | 亚洲阿v天堂 | 波多野一区二区三区 | 天天干天天色天天 | 超碰福利在线 | 亚洲精品第五页 | 在线视频网站 | 国产精品jizz在线观看无码 | 最好看的2019中文大全在线观看 | 欧美黄色一级大片 | 四川一级毛毛片 | 狠狠爱夜夜操 | 一区二区三区色 | 久久久男人的天堂 | 精品麻豆| 成人免费视频国产免费 | 亚洲精品一区二三区 | 国产一级片免费在线观看 | 夜夜春很很躁夜夜躁 | 久久视频免费在线观看 | 久久超碰在线 | 欧美我不卡 | av国产片 | 秋霞在线一区二区 | 免费人成又黄又爽又色 | 亚洲熟女一区二区三区 | 黄片毛片在线观看 | 国产精品你懂的 | 狠狠澡 | 国产麻豆免费视频 | 欧美日韩中文字幕一区二区三区 | 91视频网页| 日本精品入口免费视频 | 亚洲视频黄| 男女日皮视频 | 国产91色 | 久久免费黄色 | 91精品国产乱码 | 亚洲毛片久久 | 亚洲a黄 | 一区二区视频播放 | 男女视频久久 | 三上悠亚久久精品 | 午夜在线观看视频 | 亚洲中文在线一区 | 人人妻人人澡人人爽精品日本 | 欧美操穴视频 | 欧美精品第一页 | 中文字幕一区二区三区不卡 | 久热一区| 中国第一毛片 | 亚洲va久久久噜噜噜久久天堂 | 免费成人高清 | 国产一区免费 | 依依成人综合网 | 亚洲欧洲综合 | 日韩女优在线视频 | 狠狠干2021 | 香蕉国产 | 成人午夜视频免费看 | 国产偷亚洲偷欧美偷精品 | 色老头一区二区 | 污的网站| 午夜色福利 | 阿娇全套94张未删图久久 | 日韩美女做爰高潮免费 | 强行挺进白丝老师翘臀网站 | 久久网站免费看 | 特级一级片 | 亚洲熟乱 | 国产精品女优 | 成人精品在线观看视频 | 张津瑜国内精品www在线 | a天堂中文字幕 | 国产一区二区三区在线看 |