kosaraju求scc 強連通分量

2021-10-04 23:57:57 字數 2978 閱讀 5383

題目要求

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

input

本題有多組資料。第一行 t 表示資料組數。每組資料開始有兩個整數 n 和 m (2 <= n <= 5000, 0 3 3

1 02 1

0 2sample output

case 1: 2

0 1case 2: 2

0 1 2

求解思路

kosaraju求scc

a認為b合適,則a->b,求scc的過程為:

兩次dfs,第一次dfs確定原圖的逆後序序列,第二次dfs在反圖中按照逆後序序列進行遍歷,每次由起點遍歷到的點即構成乙個scc

2、縮點

記錄scc相互之間能否到達,視為有向邊,為降低複雜度,在尋找scc的過程中記錄能到達的scc,因為scnt為各個scc的計數,所以當scnt改變時則找到另乙個scc,此時將可到達的scc記錄在son中,son使用set避免重複。

3、找到出度為0的scc

最大值一定為出度為0的scc,所以遍歷son,當出度為0時,從該scc中的任乙個點出發,對反圖進行dfs,記錄能到達的點,即為該scc中所有點的得票數。將結果以pairtemp;//first為scc編號,second為數量 temp.first = k; temp.second = sum - 1;的形式記錄在vector > ans;中,同時,記錄最大得票數。

4. 輸出

遍歷scc,將ans中scc得票數為最大值得scc中所有點記錄在record陣列中,然後進行sort排序,公升序輸出得票最多的同學序號,複雜度為o(n^2)

**

#include

#include

#include

#define inf -1e8

#include

#include

#include

#include

using

namespace std;

#define n 5005

int c[n]

, dfn[n]

, vis[n]

, dcnt, scnt;

//dcnt-dfs序計數,scnt-scc計數

//dfn[i]-dfs後序列中第i個點

//c[i]-i 號點所在scc編號

vector<

int> g1[n]

, g2[n]

;//g1-原圖,g2-反圖

int viscon[n]

;set<

int> con[n]

;set<

int> son[n]

;//縮點後可到達的連通分量

int t, n, m;

vector

int,

int>> ans;

void

dfs1

(int x)

void

dfs2

(int x)}}

int sum =0;

void

dfs3

(int x)

}void

kosaraju()

//第二遍dfs

for(

int i = n-

1; i >=

0; i--

)++scnt;

dfs2

(dfn[i]);

}}}int

main()

ans.

clear()

;scanf

("%d%d"

,&n,

&m);

for(

int j =

0; j < m; j++

)kosaraju()

;//縮點

/* for (int k = 0; k < n; k++)

}} */

//找到出度為0的點,計算能到達的點

//找最大值

int themax =0;

for(

int k =

1; k <= scnt; k++

) sum =0;

memset

(viscon,0,

sizeof viscon)

;dfs3

(j);

pair<

int,

int> temp;

//first為scc編號,second為數量

temp.first = k; temp.second = sum -1;

ans.

push_back

(temp)

;//出度為0的點所在的scc記錄在ans中

// cout << temp.second << endl;

if(themax < sum -1)

}}//找最大值

/* int themax = 0;

for (int k = 0; k < ans.size(); k++)}*/

//輸出

int record[n]

;int current =0;

cout <<

"case "

<< i <<

": "

<< themax << endl;

for(

int k =

0; k < ans.

size()

; k++)}

}}sort

(record, record + current)

;for

(int k =

0; k < current; k++

)else}}

}

強連通分量SCC

poj2762 題意 給出n個點,對於每個點,如果任意選擇兩點s,e,都滿足s可以到達e或者e可以到達s,則輸出yes,否則輸出no。用了白書裡的模板 參考解決思路是 首先求出原圖g的強連通分量並且縮點,求出縮點後的圖mat,並且求出縮點後所有頂點的入度in。這時我們思考下,如果原圖g要是半連通的,...

SCC(強連通分量)

1.定義 在有向圖g中,如果兩個頂點間至少存在一條路徑,稱兩個頂點強連通 sc strongly connected 有向圖中的極大強連通子圖,成為強連通分量 scc strongly connected components 下圖中,子圖為乙個強連通分量,因為頂點1,2,3,4兩兩可達,也分別是兩...

強連通分量 Kosaraju

芝士 有向圖強連通分量在有向圖g中,如果兩個頂點vi,vj間 vi vj 有一條從vi到vj的有向路徑,同時還有一條從vj到vi的有向路徑,則稱兩個頂點強連通 strongly connected 如果有向圖g的每兩個頂點都強連通,稱g是乙個強連通圖。有向圖的極大強連通子圖,稱為強連通分量。如圖中1...