強連通分量(WEEK8 C)

2021-10-05 03:43:12 字數 3036 閱讀 7910

在有向圖中,若乙個子圖中任意兩點之間可連通,則稱極大的強連通子圖為強連通分量(scc),如:

要求乙個有向圖的scc,必須了解dfs序列的前序序列、後序序列、逆後序序列(後序序列的逆序)

前序:dfs過程中第一次到達點x的次序,用d[x]表示。

後序:dfs中x點遍歷完成的次序,用f[x]表示。

下面為求各序列的過程:

求解scc的演算法:kosaraju演算法,演算法步驟:

例如:

大學班級選班長,n 個同學均可以發表意見 若意見為 a b 則表示 a 認為 b 合適,意見具有傳遞性,即 a 認為 b 合適,b 認為 c 合適,則 a 也認為 c 合適 勤勞的 tt 收集了m條意見,想要知道最高票數,並給出乙份候選人名單,即所有得票最多的同學,你能幫幫他嗎?

本題有多組資料。第一行 t 表示資料組數。每組資料開始有兩個整數 n 和 m (2 <= n <= 5000, 0 對於每組資料,第一行輸出 「case x: 」,x 表示資料的編號,從1開始,緊跟著是最高的票數。 接下來一行輸出得票最多的同學的編號,用空格隔開,不忽略行末空格!

243

3220

2133

1021

02

case 1:2

01case 2:2012

求出強連通分量後,進行縮圖,將屬於乙個scc的點用連通分量編號表示,儲存在edges3中。

縮點後,對於第i個scc,答案分為兩部分:

當前 scc 中的點,ans += scc[i] – 1(去除自己);

其它 scc 中的點: sum ( scc[ j] ),其中 j 可到達 i。

又思考一下,發現最後答案一定出現在出度為 0 的 scc中,因此我們將邊反向,對每個入度為 0 的點進行 dfs,計算其能到達的點的 sum(scc[ j]),即可得到答案。

#include

#include

#include

using

namespace std;

//有向圖

const

int maxn=

5050

;const

int maxm=

30010

;int vis[maxn]

,dfn[maxn]

,dcnt;

struct edge

edges[maxm]

,edges2[maxm]

,edges3[maxm]

;//正圖,反圖 ,縮圖

int head[maxn]

,tot,head2[maxn]

,tot2,head3[maxn]

,tot3,c[maxn]

,cnt,deg[maxn]

,vis2[maxn]

;int maxv=

0,cn[maxn]

,sum[maxn]

,res;

//儲存最大票數、每個連通分量有幾個節點

void

init()

void

addedge

(int _u,

int _v,

int type)

else

if(type==2)

//反圖

else

if(type==3)

//縮圖的反圖

}void

dfs1

(int s)

dfn[

++dcnt]

=s;//計算逆後序序列

}void

dfs2

(int s)

void

dfs3

(int s)

}void

kosarajo

(int n)

for(

int i=n;i>=

1;i--

)//按照逆後序順序遍歷,記錄每個點屬於哪個強連通分量

if(c[dfn[i]]==

-1)}

void

degezero()

}}intmain()

//找到強連通分量

kosarajo

(n);

//for(int i=0;i//建立縮圖的反圖

for(

int i=

0;i)for

(int j=head[i]

;j!=-1

;j=edges[j]

.next)

}//找到入度為0的連通分量並計算可到達的點的個數

degezero()

;printf

("case %d: %d\n"

,tt,res)

;int k=0;

for(

int i=

0;i)else

printf

(" %d"

,i);}}

tt++

;printf

("\n");

}return0;

}

強連通分量 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演算法求強連通分量。define n 1000 struct edge e 100000 int ec,p...

強連通分量

在有向圖g中,如果兩個頂點間至少存在一條路徑,稱兩個頂點強連通 strongly connected 如果有向圖g的每兩個頂點都強連通,稱g是乙個強連通圖。非強連通圖有向圖的極大強連通子圖,稱為強連通分量 strongly connected components 下圖中,子圖為乙個強連通分量,因為...