利用鄰接矩陣求解無向圖的連通分支的個數

思路一:Warshall算法
對鄰接矩陣運行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;
			}
		}
	}
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章