強力な接続コンポーネントとは
有向グラフ:
1. 2つのポイントが有向エッジを介して相互に接続できる場合、2つのポイントは強い接続と呼ばれます。
2.グラフ内のいずれかの2つのポイントが強く接続されている場合、有向グラフは強く接続されたグラフと呼ばれます(ポイントも強く接続されたグラフです)。
3.非強連結グラフ内の非常に大きな強連結サブグラフ(別のより大きな強連結サブグラフには含まれていません)は、このグラフの強連結コンポーネントと呼ばれます。
図に示すように:
グラフの強連結成分は、{1,2,4}と{3}です。
強く接続されたコンポーネントには、いくつかの明らかな特性があることがわかります。
1.強く接続された各コンポーネントに繰り返し点はありません。
2.強連結成分では、任意の点uは、有向エッジを通過するすべての点を通過し、最終的に点uに戻ることができます。
タージャンとは
上記の結論から、強連結成分は最大方向のリングであることがわかります。
いわゆるtarjanはDFSに関連している必要があります(理由は聞かないでください)。ポイントuDFSから開始して、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]であり、low [u] = min(low [u]、low [v]);
5.最後に、dfn [u]がlow [u]と等しい場合、スタックではポイントがuから検索されるため、uから下に検索するとuに戻る(またはuから下に検索する)ことを意味します。すべてがuに積み上げられるため、スタック内のuに積み上げられたポイントは、uとともにスタックからポップされ、強連結成分として分類されます。
uによって検出されたすべての点のうち、有向エッジを介してuに戻れない(uに強く接続できない)点、またはuよりもdfn値が大きい点vに接続されて、小さなリングを形成している点、そしてスタックからポップアウトされます;
リングが形成されていないか、低い値がdfn値と同じままであり、スタックからポップされます(これはポイントの強力な接続コンポーネントです)。
したがって、uのスタック内の残りのポイントは、uに強く接続できるすべてのポイントです。
たとえば、上の画像は次のとおりです。
ポイント1から検索:
2から4まで検索します。
4は1に接続されており、1がスタック内にあり、変更が少なく、2にバックトラックしていることがわかります。
次に、2から3まで検索します。
3再度検索できません、dfn = low、スタックからポップアウトします:
最後に1に戻り、dfn = low、1、2、および4が一緒にスタックからポップされていることを確認します。
{3}、{1,2,4}の2つの強連結成分を見つけます。
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);
}
}