给定一个有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 }
/*
Name:06-图1 列出连通集 (25分)
Copyright:
Author: Ambition
Date: <08/12/19 21:28>
Description:
*/
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <vector>
#include <cstring>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <algorithm>
using namespace std;
typedef long long ll;
#define INF 1<<30
#define MaxVertexNum 100 // 顶点数目的最大值
typedef int VertexType; // 顶点的数据类型
typedef int EdgeType; // 带权图边上的权值数据类型
typedef int InfoType; // 边的信息,如权值
typedef int ElemType; // 元素类型
bool visited[MaxVertexNum]; // 顶点访问标记数组
struct ArcNode{ // 边表结点
int adjvex; // 该弧所指向的顶点的位置
ArcNode* next; // 指向下一条弧的指针
// InfoType info; // 网的边权值
};
struct MGraph{ // 定义邻接矩阵
VertexType Vex[MaxVertexNum]; // 顶点表
EdgeType Edge[MaxVertexNum][MaxVertexNum]; // 邻接矩阵,边表
int vexnum, arcnum; // 图当前顶点和弧数
};
typedef struct VNode{ // 顶点表结点
VertexType data; // 顶点信息
ArcNode* first; // 指向第一条依附该顶点的指针
} VNode, AdjList[MaxVertexNum];
struct ALGraph{
AdjList vertices; // 邻接表
int vexnum, arcnum; // 图的顶点数量和边的数量
};
void CreatALGraphAndMGraph(ALGraph &ALG, MGraph &MG);
void PrintG(MGraph MG);
void PrintG(ALGraph ALG);
void visit(ALGraph &G, int v);
void visit(MGraph &G, int v);
void DFS(ALGraph G, int v);
void DFS(MGraph G, int v) ;
void DFSTraverse(ALGraph G);
void DFSTraverse(MGraph G) ;
//void BFS(MGraph G);
void CreatALGraphAndMGraph(ALGraph &ALG, MGraph &MG);
void InsertArc(ALGraph &ALG,int v,int w);
int countConnectedByBFS(MGraph &G) ;
int countConnectedByBFS(ALGraph &G);
int main(int argc, char** argv) {
//freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
int i,v,w;
ALGraph ALG;//邻接表
MGraph MG;//
CreatALGraphAndMGraph(ALG,MG);
//PrintG(ALG);
DFSTraverse(ALG);
countConnectedByBFS(ALG);
return 0;
}
void PrintG(MGraph MG){
int i,j,n;
n=MG.vexnum;
for(i=0; i<n; i++){
for(j=0; j<n; j++){
printf(" %d",MG.Edge[i][j]);
}
printf("\n");
}
for(i=0;i<n;i++){
printf("V[%d]:%d ",i,visited[i]);
}
printf("\n");
}
void PrintG(ALGraph ALG){
int i,j,n;
n=ALG.vexnum;
for(i=0; i<n; i++){
printf("V[%d]=%d ",i,ALG.vertices[i].data);
ArcNode *p=ALG.vertices[i].first;
for(; p!=NULL; p=p->next){
printf(" ->%d ",p->adjvex);
}
printf("\n");
}
}
void visit(ALGraph &G, int v) {
printf(" %d", G.vertices[v].data);
}
void visit(MGraph &G, int v) {
printf(" %d", G.Vex[v]);
}
void DFS(ALGraph G, int v) {
// 从顶点v出发递归的深度优先遍历图G(包含v的连通块)
visited[v] = true; // 标记顶点v访问
visit(G, v); // 访问顶点v
for(ArcNode* p = G.vertices[v].first; p!=NULL; p=p->next) { // 对顶点v尚未访问的邻接顶点p递归调用DFS
if(!visited[p->adjvex]) {
DFS(G, p->adjvex);
}
}
}
void DFS(MGraph G, int v) {
// 从顶点v出发递归的深度优先遍历图G(包含v的连通块)
visited[v] = true; // 标记顶点v访问
visit(G, v); // 访问顶点v
for(int w=0; w<G.vexnum; w++) { // 对顶点v尚未访问的邻接顶点w递归调用DFS
if(G.Edge[v][w]>0&&!visited[w]) {
DFS(G,w);
}
}
}
void DFSTraverse(ALGraph G) {
for(int i=0; i<G.vexnum; i++)
visited[i] = false; // 标记所有顶点为没有访问
for(int i=0; i<G.vexnum; i++) { // 对所有没有访问的顶点i调用DFS访问该顶点所在连通块
if(!visited[i]) {
printf("{");
DFS(G, i);
printf(" }\n");
}
}
}
void DFSTraverse(MGraph G) {
for(int i=0; i<G.vexnum; i++)
visited[i] = false; // 标记所有顶点为没有访问
for(int i=0; i<G.vexnum; i++) { // 对所有没有访问的顶点i调用DFS访问该顶点所在连通块
if(!visited[i]) {
printf("{");
DFS(G, i);
printf(" }\n");
//PrintG(G);
}
}
}
int countConnectedByBFS(ALGraph &G){
int i,v;
for(v=0; v<G.vexnum; v++) visited[v]=false;
queue<int> Q; int cnt=0;
for(v=0; v<G.vexnum; v++){
if(!visited[v]){
cnt++;
printf("{");
visited[v]=true;
visit(G,v);
Q.push(v);
while(!Q.empty()){
int w=Q.front();
Q.pop();
ArcNode *p=G.vertices[w].first;
for( ; p!=NULL; p=p->next){
if(!visited[p->adjvex]){
visited[p->adjvex]=true;
visit(G,p->adjvex);
Q.push(p->adjvex);
}
}//for
}//while
printf(" }\n");
}//if
}//for
return cnt;
}//BFS
int countConnectedByBFS(MGraph &G) {
for(int v=0; v<G.vexnum; v++) // 标记所有顶点为没有访问
visited[v] = false;
queue<int> Q; // 保存正在访问的结点队列
int cnt = 0; // 统计连通块数量
for(int v=0; v<G.vexnum; v++) { // 遍历所有没有访问的结点
if(!visited[v]) {
cnt++; // 连通块数量增一
printf("{");
visited[v] = true; // 从当前结点开始BFS访问所在连通块的所有结点
//printf(" v=%d ",v);
visit(G,v);
Q.push(v); // 加入队列
while(!Q.empty()) {
int w = Q.front(); // 弹出队首元素
Q.pop();
for(int i=0; i<G.vexnum; i++) { // 对顶点w尚未访问的邻接顶点i进行访问并入栈
if(G.Edge[w][i]>0 && !visited[i]) {
visited[i] = true;
visit(G,i);
Q.push(i);
}
}
}
printf(" }\n");
//PrintMG(G);
}
}
return cnt;
}
void InsertArc(ALGraph &ALG,int v,int w){
//向邻接表中插入一条<v,w>的边
ArcNode * s=(ArcNode *)malloc(sizeof(struct ArcNode)), *p;
s->next=NULL;
s->adjvex=w; p=ALG.vertices[v].first;
if(ALG.vertices[v].first==NULL||w<p->adjvex){//
s->next=ALG.vertices[v].first;
ALG.vertices[v].first=s;
}
else{
int temp;
while(p->next!=NULL&&w>p->adjvex) p=p->next;
if(p->next==NULL&&w>p->adjvex){
p->next=s;
}
else{
s->next=p->next;//先插入
p->next=s;
temp=s->adjvex;//然后交换数据
s->adjvex=p->adjvex;
p->adjvex=temp;
}
}
//printf("insert <%d,%d>\n",v,w);
//PrintG(ALG);
}
void CreatALGraphAndMGraph(ALGraph &ALG, MGraph &MG){
int i,j,k,v,e;
scanf("%d%d",&v,&e); //输入顶点数v和边数e
ALG.vexnum=v; ALG.arcnum=e;
MG.vexnum=v; MG.arcnum=e;
for(i=0; i<v; i++){
ALG.vertices[i].data=i;
ALG.vertices[i].first=NULL;
MG.Vex[i]=i;
}
for(k=0; k<e; k++){
scanf("%d%d",&i,&j);
InsertArc(ALG,i,j);
InsertArc(ALG,j,i);
MG.Edge[i][j]=MG.Edge[j][i]=1;
}
}

本文介绍了一种使用深度优先搜索(DFS)和广度优先搜索(BFS)算法来遍历无向图中所有连通集的方法。通过具体实例展示了如何从编号最小的顶点出发,按递增顺序访问邻接点,最终列出所有连通集。

8496

被折叠的 条评论
为什么被折叠?



