一、概念
什麼是連通、強連通、弱連通?
這裡有比較好理解的概念
二、方法
(所涉及的內容皆圍繞cf999e)
我們在計算強連通分量的時候會用到的工具
三、縮點
前面已經提到強連通分量的定義,即任意i點可以到達任意j點
那麼要是在強連通分量中再新增路徑就沒有必要
所以就可以把同屬於乙個強連通分量的節點看為同乙個節點
構建為乙個新的有向圖
對於新的節點,我們需要
for
(int i =
1; i <= n ; i ++
)for
(int j =
0; j < ve[ i ]
.size()
; j ++
)///有關全域性變數已在前文明示
因為題目中詢問的從s結點出發能夠遍歷全部節點
那麼只需分析除s所在新節點外的新節點的入度
(若與s在同一新節點,則s一定可以到達)
若入度為0,則需要建一條新的有向邊
最後附上該題ac**
#include
#include
#include
#include
using
namespace std;
vector<
int> ve[
5005];
stack<
int> st;
int tim=1;
///時間戳
int dfn[
5005];
///真實的被訪問的順序
int low[
5005];
///可以到達的最早的時間點
int bel[
5005];
int in[
5005];
bool instack[
5005];
///記錄在棧裡的節點
int cnt=0;
void
dfs(
int node)
else
if(instack[ve[node]
[i]]
/*y in stack*/)}
if(dfn[node]
==low[node]
) instack[st.
top()]
=0; bel[st.
top()]
=cnt;
st.pop();
}}intmain()
///存單向圖
for(
int i=
1; i<=n; i++
)for
(int i =
1; i <= n ; i ++
)for
(int j =
0; j < ve[ i ]
.size()
; j ++
)int ans =0;
for(
int i =
1; i <= cnt ; i ++)if
(!in[ i ]
&& i != bel[ s ]
) ans ++
;printf
("%d\n"
,ans)
;return0;
}/*5 5 1
1 22 3
3 44 2
4 5///上圖測試資料
*/
不定時更新~~~ Tarjan求連通分量 縮點
1.強連通 在乙個圖中對於任意兩個點都可以互相到達那麼就稱這個圖為強連通圖。連通分量 乙個圖的極大強連通子圖,稱為強連通分量 乙個連通分量比較類似於乙個集合,裡面的任點都可以互相到達 縮點 把乙個連通分量整體看作是乙個節點,那麼這個節點就是縮點 2.tarjan演算法 考慮維護三個陣列 vis,df...
強連通分量 tarjan求強連通分量
雙dfs方法就是正dfs掃一遍,然後將邊反向dfs掃一遍。挑戰程式設計 上有說明。雙dfs 1 include 2 include 3 include 4 include 5 6using namespace std 7const int maxn 1e4 5 8 vector g maxn 圖的鄰...
強連通分量及縮點tarjan演算法解析
再次深搜 此時 stack 發現綠邊指向了已經遍歷過的點4 是上述的2種邊之一 而4在棧中 4點與6點是父子關係 該邊為後向邊 4 6的路徑上的點都是環。int num n top 0 int u stack.top while u 4 num top u 如此就能把stack中 4 6路徑上的點轉...