利用邻接矩阵求解无向图的连通分支的个数

思路一: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;
			}
		}
	}
}


猜你喜欢

转载自blog.csdn.net/EsonJohn/article/details/52403185