用DFS和BFS求連通分量(鄰接表的實現與應用)

2021-07-25 06:27:38 字數 1775 閱讀 6500

本文內容改編自《挑戰程式設計競賽(第2彈)》12.5節

給出朋友關係,判斷從指定人物出發能否通過雙向朋友鏈抵達目標人物。

輸入

第一行輸入總人數n以及朋友關係數m

人的編號從0到n-1。

接下來m行輸入朋友關係,每個朋友關係佔一行。

1個朋友關係包含s、t兩個整數,表示s和t為朋友。

接下來一行輸入問題數q。再接下來q行輸入問題

各問題為兩個整數s、t。表示「從s能否抵達t?」

輸出

如果從s出發能抵達t就輸出yes,否則輸出no,每個問題的回答佔1行。

限制

1 < n < 100000, 0 < m < 100000, 1 < q < 10000

樣例輸入

10 9

0 1

0 2

3 4

5 7

5 6

6 7

6 8

樣例輸出

yes

yes

no這道題就是求給定的圖的連通分量問題,可以用「種子填充」的思想來解決此題。

對圖中每乙個結點進行深度優先搜尋,並在此過程中對還沒有填色的結點填填色。

如果兩個結點有相同的顏色,那麼這兩個結點就是連通的。

於是o(1)時間就可以判斷指定兩個結點是否連通。

核心演算法就是dfs。主要資料結構就是鄰接表,用來儲存圖的資訊。

在鄰接表上的dfs需要需要對每個頂點,每個邊都要訪問一次,演算法複雜度為

o(|v|+|e|)

在c++中,用vector可以輕鬆的實現鄰接表。

vector

g[100]; //表示100個頂點的鄰接表

g[u].push_back(v); //從頂點u向頂點v畫邊

//搜尋與頂點相鄰的頂點v

for (int i = 0; i < g[u].size(); i++)

優點:只需要與邊數成正比的空間

缺點:難以有效地刪除邊

若u的相鄰頂點數量為n,需要消耗o(n)來搜尋鄰接表。

#include 

using

namespace

std;

const

int max_n = 100000;

int n;

vector

g[max_n];

int color[max_n];

//從結點r開始dfs,並填充顏色c

void dfs(int r, int c)

}}void assigncolor()

}int main()

//填色開始

assigncolor();

int q;

cin >> q;

for (int i = 0; i < q; i++) else }}

return

0;}

其中void dfs()還有另外一種實現方法,就是顯式地使用棧來實現dfs。

當然這道題也可以用廣度優先搜尋(bfs),部分**如下

void bfs(int r, int c)}}

}void assigncolor()

}

BFS 連通分量 求連通分量

題目描述 求乙個圖的連通分量 input n 頂點數 100 邊 以0 0作為結束標誌 output 連通分量 強連通圖的連通分量為其本身。如果為非連通圖,則連通分量為該圖的最大連通子圖。分析 建乙個100 100的布林矩陣,b x,y true表示x與y連通。同時還要記錄該點是否被遍歷過 然後遍歷...

求連通分量

求連通分量 time limit 1000ms memory limit 65536k total submit 233 accepted 132 description 求乙個圖的連通分量 input n 頂點數 100 邊 output 連通分量 sample input 5 1 2 3 4 2...

強連通分量 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 圖的鄰...