本文內容改編自《挑戰程式設計競賽(第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)來搜尋鄰接表。
其中void dfs()還有另外一種實現方法,就是顯式地使用棧來實現dfs。#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;}
當然這道題也可以用廣度優先搜尋(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 圖的鄰...