您的位置:首页 > 编程语言 > C语言/C++

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

2016-09-01 20:34 190 查看
思路一: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
;
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
;
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;
}
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息