對鄰接矩陣運行Warshall算法,得到連通矩陣
for (int k = 0; k < N; k++)
{
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
G[i][j] = G[i][j] || (G[i][k] && G[k][j]);
}
}
}
再定義visited參考矩陣,visited[i]代表第i個頂點是否被標記,每一輪從第一個還沒有被標記的節點(記爲X)開始,找出剩下的所有沒被標記的頂點中與X節點連通的節點,並打上標記,直到所有的節點都標記上。記錄循環的輪數就是連通分支的個數
int numSection = 0;
bool *decided = new bool[N];
for (int i = 0; i < N; i++)
decided[i] = false;
int decidedNum = 0;
while (decidedNum < N)
{
//找到第一個還沒有判決的節點
int minIndex = 0;
while (decided[minIndex])
minIndex++;
decided[minIndex] = true;
decidedNum++;
numSection++;
int pos = minIndex + 1;
while (pos < N)
{
if (!decided[pos] && G[minIndex][pos])
{
decided[pos] = true;
decidedNum++;
}
pos++;
}
}
注意:該算法的時間複雜度非常高O(n^3),因此在OJ上很可能Time Limit Exceed。
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
思路二:圖的BFS(或者DFS)遍歷定義visited參考矩陣,visited[i]表示該節點是否被遍歷到,從visited[0],即第一個節點開始,如果遇到沒有被遍歷到的節點就對該節點進行BFS遍歷,直到達到visited數組的盡頭。
中途記錄調用BFS的次數即爲連通分支的個數
逐次調用BFS的代碼片段
int numSection = 0;
bool *visited = new bool[N];
for (int i = 0; i < N; i++)
visited[i] = false;
for (int i = 0; i < N; i++)
{
if (!visited[i])
{
BFS(G, N, i, visited);
numSection++;
}
}
BFS的代碼片段
void BFS(bool **const G, int edgeNum, int begin, bool *visited)
{
queue<int> Q;
Q.push(begin);
visited[begin] = true;
while (!Q.empty())
{
int tmp = Q.front();
Q.pop();
for (int i = 0; i < edgeNum; i++)
{
if (!visited[i] && G[tmp][i])
{
Q.push(i);
visited[i] = true;
}
}
}
}