Write a function to count the number of connected components in a given graph.
写一个函数来计算给定图中连通分量的数量。
Format of functions:
int CountConnectedComponents( LGraph Graph );
where LGraph is defined as the following:
typedef struct AdjVNode *PtrToAdjVNode;
struct AdjVNode{
Vertex AdjV;
PtrToAdjVNode Next;
};
typedef struct Vnode{
PtrToAdjVNode FirstEdge;
} AdjList[MaxVertexNum];
typedef struct GNode *PtrToGNode;
struct GNode{
int Nv;
int Ne;
AdjList G;
};
typedef PtrToGNode LGraph;
The function CountConnectedComponents is supposed to return the number of connected components in the undirected Graph.
Sample program of judge:
#include <stdio.h>
#include <stdlib.h>
typedef enum {false, true} bool;
#define MaxVertexNum 10 /* maximum number of vertices */
typedef int Vertex; /* vertices are numbered from 0 to MaxVertexNum-1 */
typedef struct AdjVNode *PtrToAdjVNode;
struct AdjVNode{
Vertex AdjV;
PtrToAdjVNode Next;
};
typedef struct Vnode{
PtrToAdjVNode FirstEdge;
} AdjList[MaxVertexNum];
typedef struct GNode *PtrToGNode;
struct GNode{
int Nv;
int Ne;
AdjList G;
};
typedef PtrToGNode LGraph;
LGraph ReadG(); /* details omitted */
int CountConnectedComponents( LGraph Graph );
int main()
{
LGraph G = ReadG();
printf("%d\n", CountConnectedComponents(G));
return 0;
}
/* Your function will be put here */
Sample Input (for the graph shown in the figure):
8 6
0 7
0 1
2 0
4 1
2 4
3 5
Sample Output:
3
DFS(或BFS)可以用来计算图的连通分量数,因为一次遍历必然会将一个连通图中的所有顶点都访问到,而对于已被访问的顶点将不再调用DFS(或BFS),故计算图的连通分量数正好是CountConnectedComponents( LGraph Graph );中DFS(或BFS)被调用的次数。
dfs解法:
bool visited[MaxVertexNum]; // 访问标记数组
void dfs(LGraph Graph, int v) { // 从顶点v出发,深度优先遍历图
PtrToAdjVNode p = Graph->G[v].FirstEdge;
visited[v] = true; // 设已访问标记
while(p != NULL) {
int temp = p -> AdjV;
if(!visited[temp]) { // temp为尚未访问的邻接顶点
dfs(Graph, temp);
}
p = p -> Next;
}
}
int CountConnectedComponents( LGraph Graph ){
int sum = 0;
for(int i = 0; i < Graph->Nv;i++) visited[i] = false; // 初始化已访问标记数据
for(int i = 0; i < Graph->Nv; i++) { //对图进行深度优先遍历
if(!visited[i]) {
dfs(Graph, i);
sum++;
}
}
return sum;
}
由于最近在复习图论的知识,所以顺便自己写了一份bfs求连通分量的代码
#include<bits/stdc++.h>
using namespace std;
#define MaxVertexNum 10 /* maximum number of vertices */
typedef int Vertex; /* vertices are numbered from 0 to MaxVertexNum-1 */
typedef struct AdjVNode *PtrToAdjVNode, AdjVNode;
struct AdjVNode{
Vertex AdjV;
PtrToAdjVNode Next;
};
typedef struct Vnode{
PtrToAdjVNode FirstEdge;
} AdjList[MaxVertexNum];
typedef struct GNode *PtrToGNode, GNode;
struct GNode{
int Nv;
int Ne;
AdjList G;
};
typedef PtrToGNode LGraph;
LGraph ReadG() {
int n, m, u, v;
scanf("%d%d", &n, &m);
LGraph Graph;
Graph = (LGraph) malloc (sizeof(GNode));
Graph->Nv = n, Graph->Ne = m;
for(int i = 0; i < n; i++) {
Graph->G[i].FirstEdge = NULL;
}
AdjVNode *p, *q;
for(int i = 0; i < m; i++) {
scanf("%d%d", &u, &v);
p = (AdjVNode *) malloc (sizeof(AdjVNode));
p -> AdjV = v;
p -> Next = Graph->G[u].FirstEdge;
Graph->G[u].FirstEdge = p;
q = (AdjVNode *) malloc (sizeof(AdjVNode));
q -> AdjV = u;
q -> Next = Graph->G[v].FirstEdge;
Graph->G[v].FirstEdge = q;
}
return Graph;
}
int CountConnectedComponents( LGraph Graph );
void print(LGraph Graph) {
for(int i = 0; i < Graph->Nv; i++) {
printf("(%d) ->", i);
AdjVNode *p = Graph->G[i].FirstEdge;
while(p) {
printf("%d->", p->AdjV);
p = p->Next;
}
cout << endl;
}
}
int main()
{
LGraph G = ReadG();
print(G);
printf("%d\n", CountConnectedComponents(G));
return 0;
}
/* Your function will be put here */
const int Maxsize = 50; // 定义队列中元素的最大个数
typedef struct {
int data[Maxsize]; // 存放队列元素
int front, rear; // 队头指针和队尾指针
}SqQueue;
void InitQueue(SqQueue &Q) {
Q.rear = Q.front = 0; // 初始化队首队尾指针
}
bool isEmpty(SqQueue Q) {
return Q.rear == Q.front; //队空条件
}
bool EnQueue(SqQueue &Q, int x) {
if((Q.rear+1)%Maxsize == Q.front) return false; //队满则报错
Q.data[Q.rear] = x;
Q.rear = (Q.rear+1)%Maxsize; //队尾指针加一取模
return true;
}
bool DeQueue(SqQueue &Q, int &x) {
if(Q.rear == Q.front) return false; // 队空则报错
x = Q.data[Q.front];
Q.front = (Q.front+1) % Maxsize; //队头指针加一取模
return true;
}
bool visited[100]; //访问标记数组
SqQueue Q;
void bfs(LGraph Graph, int v) { // 从顶点v出发,广度优先遍历图G
visited[v] = true; //对v做已访问标记
EnQueue(Q, v); //顶点V入队列
while (!isEmpty(Q))
{
DeQueue(Q, v); //顶点v出队
PtrToAdjVNode p = Graph->G[v].FirstEdge;
while(p != NULL) { //检测v所有邻接点
int w = p -> AdjV;
if(!visited[w]) { //w为v的尚未访问的邻接顶点
visited[w] = true; //对w做已访问标记
EnQueue(Q, w); // 顶点w入队列
}
p = p->Next;
}
}
}
int CountConnectedComponents( LGraph Graph ) {
for(int i = 0; i < Graph->Nv; i ++) visited[i] = false; //对标记数组初始化
InitQueue(Q); // 初始化辅助队列
int sum = 0;
for(int i = 0; i < Graph->Nv; i++) { //从0号顶点开始遍历
if(!visited[i]) { //对每个连通分量调用一次bfs
bfs(Graph, i); //vi未访问过,从vi开始bfs
sum++;
}
}
return sum;
}
/*
8 6
0 7
0 1
2 0
4 1
2 4
3 5
*/