题目描述
给定一个有 N 个顶点和 E 条边的无向图,请用 DFS 和 BFS 分别列出其所有的连通集。假设顶点从 0 到 N−1 编号。进行搜索时,假设我们总是从编号最小的顶点出发,按编号递增的顺序访问邻接点。
输入格式
输入第 1 行给出 2 个整数 N(0 < N ≤ 10) 和 E,分别是图的顶点数和边数。随后 E 行,每行给出一条边的两个端点。每行中的数字之间用1空格分隔。
输出格式
按照”{ v1 v2 … vk }”的格式,每行输出一个连通集。先输出 DFS 的结果,再输出 BFS 的结果。
输入样例
1 2 3 4 5 6 7
| 8 6 0 7 0 1 2 0 4 1 2 4 3 5
|
输出样例
1 2 3 4 5 6
| { 0 1 4 2 7 } { 3 5 } { 6 } { 0 1 2 7 4 } { 3 5 } { 6 }
|
C语言实现
首先我们需要分别定义图和边,这里我们使用邻接矩阵来存储图:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| #define MaxVertex 10
typedef struct GNode* MGraph; struct GNode{ int Nv; int Ne; int data[MaxVertex][MaxVertex]; };
typedef struct ENode* Edge; struct ENode { int V1,V2; };
|
然后我们需要三个方法,分别来创建一个有 Vertex 个顶点,但没有边的图,然后需要一个方法来将边插入图中,最后用一个方法来创建图。
1 2 3 4 5 6 7
| MGraph CreateGraph(int Vertex);
void InsertEdge(MGraph Graph,Edge E);
MGraph BuildGraph();
|
图创建完成之后,我们需要分别实现 DFS 和 BFS,因此:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| int Visited[MaxVertex];
typedef struct QNode* Queue; struct QNode { int front; int rear; int MaxSize; int* data; };
void DFS(MGraph Graph, int V);
void BFS(MGraph Graph, int V);
Queue CreateQueue(int MaxSize); void AddQ(Queue Q, int X); int DeleteQ(Queue Q); int IsEmpty(Queue Q);
|
接下来就依次实现这些方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
| MGraph CreateGraph(int Vertex) { MGraph Graph = (MGraph)malloc(sizeof(struct GNode)); Graph->Nv = Vertex;
for(int V = 0;V < Graph->Nv;V++) { for(int W = 0;W < Graph->Nv;W++) { Graph->data[V][W] = 0; } }
return Graph;
}
void InsertEdge(MGraph Graph,Edge E) { Graph->data[E->V1][E->V2] = 1; Graph->data[E->V2][E->V1] = 1;
}
MGraph BuildGraph() { int Nv;
scanf("%d",&Nv);
MGraph Graph = CreateGraph(Nv);
scanf("%d",&Graph->Ne);
if(Graph->Ne != 0) {
Edge E = (Edge)malloc(sizeof(struct ENode));
for(int i = 0;i < Graph->Ne;i++) { scanf("%d %d",&E->V1,&E->V2);
InsertEdge(Graph, E); } }
return Graph; }
void DFS(MGraph Graph, int V){ Visited[V] = 1; printf("%d ", V);
for(int i = 0;i < Graph->Nv;i++) { if(Graph->data[V][i] == 1 && Visited[i] == -1) { DFS(Graph, i); } } } void BFS(MGraph Graph, int V){
Queue Q = CreateQueue(MaxVertex);
Visited[V] = 1;
AddQ(Q, V);
while(!IsEmpty(Q)) { int W = DeleteQ(Q); printf("%d ", W); for(int i = 0;i < Graph->Nv;i++) { if(Graph->data[W][i] == 1 && Visited[i] == -1) { Visited[i] = 1; AddQ(Q, i); } } }
} Queue CreateQueue(int MaxSize) { Queue Q = (Queue)malloc(sizeof(struct QNode)); Q->front = -1; Q->rear = -1; Q->MaxSize = MaxSize; Q->data = (int*)malloc(MaxSize*sizeof(int)); return Q; } void AddQ(Queue Q, int X) {
Q->rear = (Q->rear +1)%(Q->MaxSize); Q->data[Q->rear] = X; } int DeleteQ(Queue Q) { Q->front = (Q->front+1)%(Q->MaxSize); return Q->data[Q->front]; } int IsEmpty(Queue Q) { return Q->front == Q->rear ? 1 : 0; }
|
最后在 main 函数里面依次输出连通集即可:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| int main() { MGraph Graph = BuildGraph();
for(int i = 0;i < Graph->Nv;i++) { Visited[i] = -1; } for(int V = 0;V < Graph->Nv; V++){ if(Visited[V] == -1) { printf("{ "); DFS(Graph,V); printf("}"); printf("\n"); }
}
for(int i = 0;i < Graph->Nv;i++) { Visited[i] = -1; } for(int V = 0;V < Graph->Nv; V++){ if(Visited[V] == -1) { printf("{ "); BFS(Graph,V); printf("}"); printf("\n"); }
}
return 0; }
|