1. 程式人生 > >淺談Targan算法

淺談Targan算法

algo amp memset 兩個 truct else struct tdi visit

Targan算法是用來處理強連通問題(a->b且b->a)

Targan算法裏面需要定義兩個數組dfn與low並通過棧來實現.

1,dfn[x]: x是第幾個入棧的。
2,low[x]: 節點x能夠回溯到的最早位於棧中的節點。
判斷結束的條件就是當滿足low[x]==dfn[x];可以理解為low[x]經過一系列的轉換還是回到自身說明這個環(通過棧來實現)裏面的元素可以構成強連通

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<string.h>
 4 using namespace std;
5 struct node 6 { 7 int v,next; 8 } edge[1001]; 9 int DFN[1001],LOW[1001]; 10 int stack[1001],heads[1001],visit[1001],cnt,tot,index; 11 void add(int x,int y)//鏈式前向心 12 { 13 edge[++cnt].next=heads[x]; 14 edge[cnt].v = y; 15 heads[x]=cnt; 16 return ; 17 } 18 void tarjan(int x)//代表第幾個點在處理。遞歸的是點。
19 { 20 DFN[x]=LOW[x]=++tot; 21 stack[++index]=x; 22 visit[x]=1;//表示在棧裏 23 for(int i=heads[x]; ~i ;i=edge[i].next) 24 { 25 if(!DFN[edge[i].v]) //如果沒訪問過 26 { 27 tarjan(edge[i].v);//往下進行延伸,開始遞歸 28 LOW[x]=min(LOW[x],LOW[edge[i].v]);//遞歸出來,比較誰是誰的兒子/父親,就是樹的對應關系,涉及到強連通分量子樹最小根的事情。
29 } 30 else if(visit[edge[i].v ]) //如果訪問過,並且還在棧裏。 31 { 32 LOW[x]=min(LOW[x],DFN[edge[i].v]);//比較誰是誰的兒子/父親。就是鏈接對應關系 33 } 34 } 35 if(LOW[x]==DFN[x]) //發現是整個強連通分量子樹裏的最小根。 36 { 37 do 38 { 39 printf("%d ",stack[index]); 40 visit[stack[index]]=0; 41 index--; 42 } 43 while(x!=stack[index+1]); //出棧,直到找到最小根。 44 printf("\n"); 45 } 46 return ; 47 } 48 int main() 49 { 50 memset(heads,-1,sizeof(heads)); 51 int n,m; 52 scanf("%d%d",&n,&m); 53 int x,y; 54 for(int i=1; i<=m; i++) 55 { 56 scanf("%d%d",&x,&y); 57 add(x,y); 58 } 59 for(int i=1; i<=n; i++) 60 if(!DFN[i])tarjan(i);//當這個點沒有訪問過,就從此點開始。防止圖沒走完 61 return 0; 62 }

代碼運行過程如下所示:

技術分享圖片

可以觀察到,targan算法主要就是通過low[]來進行轉移,dfn[x]可以看成第幾個入棧,判斷當low[x]==dfn[x]的時候就出棧。

淺談Targan算法