Что такое сильный компонент связи
В ориентированном графе:
1. Если две точки могут быть соединены друг с другом через направленное ребро, то эти две точки называются сильной связью ;
2. Если любые две точки в графе сильно связаны, то ориентированный граф называется сильно связным графом (точка также является сильно связным графом);
3. Очень большой подграф с сильной связью в графе с несильной связью (не включаемый в другой более крупный подграф с сильной связью ) называется компонентой сильной связности этого графа .
Как показано на рисунке:
Компоненты сильной связности в графе: {1,2,4} и {3}.
Видно, что сильно связанные компоненты имеют несколько очевидных характеристик:
1. В каждой сильно связной компоненте не будет повторяющихся точек.
2. В сильно связном компоненте любая точка u может пройти через все точки через направленное ребро и, наконец, вернуться в точку u.
Что такое тарджан
Из сделанных выше выводов видно, что сильно связная компонента является максимально направленным кольцом.
Так называемый tarjan должен быть связан с DFS (не спрашивайте меня, почему). Предположим, что начиная с точки u DFS, если u находится в сильно связном компоненте, то в конце обязательно вернется в точку u.
Конкретная реализация алгоритма tarjan:
1. Используйте dfn [u], чтобы записать поисковый номер u (указывая, что u - это искомая точка);
2. Используйте low [u], чтобы представить точку с наименьшим поисковым номером, который можно найти вниз от u, и инициализируйте low [u] как dfn [u];
3. Поместите u в стек, и точки на станции представляют точки, которые не были классифицированы как сильно связанные компоненты;
4. Перечислите точки, соединенные u, выполните поиск вниз и установите эту точку как v. Если v находится в стеке, то есть v был найден и не классифицирован как компонент с сильной связью, тогда low [u] = min (low [u], dfn [v]); если v не был найден, то v не должен классифицироваться как сильно связный компонент, тогда DFS [v] и record low [u] = min (low [u], low [v]);
5. Наконец, если dfn [u] равно low [u], это означает, что поиск вниз от u вернется к u (или поиск вниз от u), потому что в стеке точка ищется вниз от u. все сложены на u, поэтому точки, сложенные на u в стопке, выталкиваются из стопки с u и классифицируются как сильно связный компонент.
Среди всех точек, найденных u, точка, которую нельзя вернуть в u через направленное ребро (она не может быть сильно связана с u), или она соединена с точкой v с большим значением dfn, чем u, образуя небольшое кольцо , а затем извлекается из стека ;
Либо кольцо не сформировано, низкое значение остается таким же, как значение dfn, и оно будет вытолкнуто из стека (это компонент сильной связи точки),
Следовательно, все остальные точки в стеке на u - это точки, которые могут быть сильно связаны с u.
Например, картинка выше:
Искать из точки 1:
Искать вниз от 2 до 4:
4 соединяется с 1, обнаруживается, что 1 находится в стеке, меняется низкий уровень и возвращается к 2:
Далее ищите от 2 до 3:
3 Невозможно снова выполнить поиск, dfn = low, выскакивает из стека:
Наконец, вернувшись к 1, обнаруживаем, что dfn = low, 1, 2 и 4 выскакивают из стека вместе:
Найдите 2 компоненты сильной связности: {3}, {1,2,4}.
основной код tarjan
void tarjan(int x){
dfn[x]=low[x]=IN++;
in_s[x]=1;
S.push(x);
for(int i=0;i<G[x].size();i++){
if(!dfn[G[x][i]]){
tarjan(G[x][i]);
low[x]=min(low[x],low[G[x][i]]);
}
else if(in_s[G[x][i]])low[x]=min(low[x],dfn[G[x][i]]);
}
if(dfn[x]==low[x]){
num++;int v;
do{
v=S.top();
S.pop();
belong[v]=num;
M[num]=min(M[num],mn[v]);
in_s[v]=0;
}while(v!=x);
}
}