06-图1 列出连通集 (25分)

题目描述

给定一个有N个顶点和E条边的无向图,请用DFS和BFS分别列出其所有的连通集。假设顶点从0到N?1编号。进行搜索时,假设我们总是从编号最小的顶点出发,按编号递增的顺序访问邻接点。

输入格式:

输入第1行给出2个整数N(0<N≤10)和E,分别是图的顶点数和边数。随后E行,每行给出一条边的两个端点。每行中的数字之间用1空格分隔。

输出格式:

按照"{v1 v2 ... vk}"的格式,每行输出一个连通集。先输出DFS的结果,再输出BFS的结果。

输入样例:

8 6
0 7
0 1
2 0
4 1
2 4
3 5

输出样例:

{ 0 1 4 2 7 }
{ 3 5 }
{ 6 }
{ 0 1 2 7 4 }
{ 3 5 }
{ 6 }

解题思路

首先选择用什么方式表示图,邻接矩阵还是邻接表。根据题意:按编号递增的顺序访问邻接点,如果用邻接表的话插入的时候就很麻烦,因为需要额外的判断来保证递增顺序,所以我选择了用邻接矩阵表示图。那么可以先根据输入构建邻接矩阵,然后再对矩阵DFS和BFS。对于DFS,每遇到一个未访问邻接点就递归;对于BFS,和二叉树的层次遍历类似,借助于队列实现,每遇到一个未访问邻接点就入队。

代码

#include <stdio.h>
#include <stdlib.h>

#define MAXSIZE 10

struct Graph {
    int vertexCount;    //顶点数
    int edgeCount;      //边数
    int matrix[MAXSIZE][MAXSIZE];   //用邻接矩阵表示图
};
typedef struct Graph *MGraph;

//用链表表示队列
struct QNode {
    int data;
    struct QNode *next;
};
typedef struct QNode *Queue;

int visited[MAXSIZE] = {0};     //判断结点是否访问过

MGraph createGraph(int N, int M);
void listConnectedSet_DFS(MGraph graph);
void listConnectedSet_BFS(MGraph graph);
void DFS(MGraph graph, int index);
void BFS(MGraph graph, int index);
Queue createQueue();
void pushQueue(Queue queue, int index);
int popQueue(Queue queue);
int isEmpty(Queue queue);

int main() {
    int N, M;
    scanf("%d %d", &N, &M);
    MGraph graph = createGraph(N, M);
    listConnectedSet_DFS(graph);
    for (int i = 0; i < N; i++) {   //重置访问数组
        visited[i] = 0;
    }
    listConnectedSet_BFS(graph);
    return 0;
}

//创建无向图
MGraph createGraph(int N, int M) {
    MGraph graph = (MGraph) malloc(sizeof(struct Graph));
    graph->vertexCount = N;
    graph->edgeCount = M;
    for (int i = 0; i < MAXSIZE; i++) {
        for (int j = 0; j < MAXSIZE; j++) {
            graph->matrix[i][j] = 0;
        }
    }
    for (int i = 0; i < M; i++) {
        int v1, v2;
        scanf("%d %d", &v1, &v2);
        graph->matrix[v1][v2] = 1;
        graph->matrix[v2][v1] = 1;
    }
    return graph;
}

//对整个图DFS
void listConnectedSet_DFS(MGraph graph) {
    for (int i = 0; i < graph->vertexCount; i++) {
        if (!visited[i]) {
            printf("{");
            DFS(graph, i);
            printf(" }\n");
        }
    }
}

//对整个图BFS
void listConnectedSet_BFS(MGraph graph) {
    for (int i = 0; i < graph->vertexCount; i++) {
        if (!visited[i]) {
            printf("{");
            BFS(graph, i);
            printf(" }\n");
        }
    }
}

//对一个连通集DFS
void DFS(MGraph graph, int index) {
    visited[index] = 1;
    printf(" %d", index);
    for (int i = 0; i < graph->vertexCount; i++) {
        if (graph->matrix[index][i] == 1 && !visited[i]) {
            DFS(graph, i);
        }
    }
}

//对一个连通集BFS
void BFS(MGraph graph, int index) {
    Queue queue = createQueue();
    pushQueue(queue, index);
    visited[index] = 1;
    printf(" %d", index);
    while (!isEmpty(queue)) {
        int index = popQueue(queue);
        for (int i = 0; i < graph->vertexCount; i++) {
            if (graph->matrix[index][i] == 1 && !visited[i]) {
                pushQueue(queue, i);
                printf(" %d", i);
                visited[i] = 1;
            }
        }
    }
}

//新建队列,返回哨兵结点
Queue createQueue() {
    Queue queue = (Queue) malloc(sizeof(struct QNode));
    queue->data = -1; queue->next = NULL;
    return queue;
}

//尾插法入队
void pushQueue(Queue queue, int index) {
    Queue rear = queue;
    while (rear->next) rear = rear->next;
    Queue node = (Queue) malloc(sizeof(struct QNode));
    node->data = index; node->next = NULL;
    rear->next = node;
}

//删除首结点
int popQueue(Queue queue) {
    if (!queue->next) return -1;
    Queue target = queue->next;
    int ret = target->data;
    queue->next = target->next;
    free(target);
    return ret;
}

//判断队列是否为空
int isEmpty(Queue queue) {
    return queue->next == NULL;
}

原文地址:https://www.cnblogs.com/AndyHY-Notes/p/12580317.html

时间: 2024-08-07 03:13:46

06-图1 列出连通集 (25分)的相关文章

PTA - - 06-图1 列出连通集 (25分)

06-图1 列出连通集   (25分) 给定一个有NN个顶点和EE条边的无向图,请用DFS和BFS分别列出其所有的连通集.假设顶点从0到N-1N−1编号.进行搜索时,假设我们总是从编号最小的顶点出发,按编号递增的顺序访问邻接点. 输入格式: 输入第1行给出2个整数NN(0<N\le 100<N≤10)和EE,分别是图的顶点数和边数.随后EE行,每行给出一条边的两个端点.每行中的数字之间用1空格分隔. 输出格式: 按照"{ v_1v?1?? v_2v?2?? ... v_kv?k?? 

06-图1 列出连通集 (25分)(C语言邻接表实现)

题目地址:https://pta.patest.cn/pta/test/558/exam/4/question/9495 由于边数E<(n*(n-1))/2 所以我选用了邻接表实现,优先队列用循环队列实现: DFS基本思路: 1:选择一个点,标志已经访问过: 2:判断这个点的其他邻接点(访问顺序按题目是从小到大)是否访问过,来选择下一个点: 3:重复第2点知道全部点已经访问过. 伪代码如下 DFS( Vertex v ) { Visit( V ); Visited[V] = true; fore

06-图1 列出连通集 (25 分)

06-图1 列出连通集 (25 分) 给定一个有N个顶点和E条边的无向图,请用DFS和BFS分别列出其所有的连通集.假设顶点从0到N?1编号.进行搜索时,假设我们总是从编号最小的顶点出发,按编号递增的顺序访问邻接点. 输入格式: 输入第1行给出2个整数N(0<N≤10)和E,分别是图的顶点数和边数.随后E行,每行给出一条边的两个端点.每行中的数字之间用1空格分隔. 输出格式: 按照"{ v?1?? v?2?? ... v?k?? }"的格式,每行输出一个连通集.先输出DFS的结果

7-1 列出连通集 (25 分)

7-1 列出连通集 (25 分) 给定一个有N个顶点和E条边的无向图,请用DFS和BFS分别列出其所有的连通集.假设顶点从0到N?1编号.进行搜索时,假设我们总是从编号最小的顶点出发,按编号递增的顺序访问邻接点. 输入格式: 输入第1行给出2个整数N(0<N≤10)和E,分别是图的顶点数和边数.随后E行,每行给出一条边的两个端点.每行中的数字之间用1空格分隔. 输出格式: 按照"{ v?1?? v?2?? ... v?k?? }"的格式,每行输出一个连通集.先输出DFS的结果,再

1142 Maximal Clique (25 分)图

1142 Maximal Clique (25 分) A clique is a subset of vertices of an undirected graph such that every two distinct vertices in the clique are adjacent. A maximal clique is a clique that cannot be extended by including one more adjacent vertex. (Quoted f

PAT 甲级 1013 Battle Over Cities (25 分)(图的遍历,统计强连通分量个数,bfs,一遍就ac啦)

1013 Battle Over Cities (25 分) It is vitally important to have all the cities connected by highways in a war. If a city is occupied by the enemy, all the highways from/toward that city are closed. We must know immediately if we need to repair any oth

列出连通集

06-图1 列出连通集(25 分) 给定一个有N个顶点和E条边的无向图,请用DFS和BFS分别列出其所有的连通集.假设顶点从0到N?1编号.进行搜索时,假设我们总是从编号最小的顶点出发,按编号递增的顺序访问邻接点. 输入格式: 输入第1行给出2个整数N(0<N≤10)和E,分别是图的顶点数和边数.随后E行,每行给出一条边的两个端点.每行中的数字之间用1空格分隔. 输出格式: 按照"{ v?1?? v?2?? ... v?k?? }"的格式,每行输出一个连通集.先输出DFS的结果,

PAT 甲级 1016 Phone Bills (25 分) (结构体排序,模拟题,巧妙算时间,坑点太多,debug了好久)

1016 Phone Bills (25 分)   A long-distance telephone company charges its customers by the following rules: Making a long-distance call costs a certain amount per minute, depending on the time of day when the call is made. When a customer starts connec

4-9 二叉树的遍历 (25分)

4-9 二叉树的遍历   (25分) 输出样例(对于图中给出的树): Inorder: D B E F A G H C I Preorder: A B D F E C G H I Postorder: D E F B H G I C A Levelorder: A B C D F G I E H 代码:(都是遍历的算法) 1 // 4-9 二叉树的遍历 2 // 3 // Created by Haoyu Guo on 04/02/2017. 4 // Copyright ? 2017 Haoy