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 }
最后输出要求一直没看懂,后来才知道原来是要给临接表的每一个表头节点后面的临接点排序。
感觉这题用临接矩阵会舒服一些,临接表纯粹是为了学习使用的
#include <iostream>
#include <deque>
#define Vertex int
#define Edge ENode
#define MAX_VERTEX 10
typedef struct _ENode //边
{
Vertex V1;
Vertex V2;
}ENode;
typedef struct _AdjVNode//临接顶点
{
Vertex AdjV;
_AdjVNode *next;
}AdjVNode;
typedef struct _VNode //顶点表头
{
AdjVNode *first_node;
}VNode[MAX_VERTEX];
typedef struct _Graph //图
{
int Vertex_num;
int Edge_num;
VNode G;
}Graph;
void creat_Graph(Graph *G, int Vnum, int Enum);
void insert_Edge(Graph *, Edge);
void BFS_components(Graph *);
void BFS(Graph *, Vertex first_V, int visited[]);
void DFS_components(Graph *);
void DFS(Graph *, Vertex first_V, int visited[]);
void print_squ();
void sort_AdjV(Graph *);
void sort_bubble(AdjVNode *);
using namespace std;
deque<Vertex> V_squ;//输出的序列
bool is_first_print = 1;
int main()
{
int N, E;
cin >> N >> E;
Graph *graph = new Graph;
Edge edge;
creat_Graph(graph, N, E);
for (int i = 0; i < E; i++)
{
cin >> edge.V1 >> edge.V2;
insert_Edge(graph, edge);
}
sort_AdjV(graph);
DFS_components(graph);
BFS_components(graph);
return 0;
}
void creat_Graph(Graph *graph, int Vnum, int Enum)
{
graph->Vertex_num = Vnum;
graph->Edge_num = Enum;
for (Vertex i = 0; i < graph->Vertex_num; i++)
graph->G[i].first_node = NULL;
}
void insert_Edge(Graph *graph, Edge edge)
{
AdjVNode *AdjV_1, *AdjV_2;
AdjV_1 = new AdjVNode;
AdjV_2 = new AdjVNode;
AdjV_1->AdjV = edge.V1;
AdjV_2->AdjV = edge.V2;
//头插法
AdjV_2->next = graph->G[edge.V1].first_node;
graph->G[edge.V1].first_node = AdjV_2;
AdjV_1->next = graph->G[edge.V2].first_node;
graph->G[edge.V2].first_node = AdjV_1;
}
//广度优先遍历(输出)所有连通分量
void BFS_components(Graph *graph)
{
int visited[MAX_VERTEX];
for (int i = 0; i < graph->Vertex_num; i++)
visited[i] = 0;
for (Vertex i = 0; i < graph->Vertex_num; i++)
if (visited[i] == 0) {
BFS(graph, i, visited);
print_squ();
V_squ.clear();
}
}
void BFS(Graph *graph, Vertex first_V, int visited[]) //入队前访问,出队后检查临接点并入队
{ //直接访问临接表中的节点,访问完入队,之后只要检查他的临界点就OK了,不要单独去访问表头节点
AdjVNode *last; //不用另外再写一个访问表头的代码,所以更加简洁,唯一一次访问表头是在开头的时候
Vertex V = first_V;
deque<Vertex>visit_queue;
V_squ.push_back(V);//访问表头
visited[V] = 1;
visit_queue.push_back(V);
while (!visit_queue.empty())
{
V = visit_queue.front();
visit_queue.pop_front();
last = graph->G[V].first_node;
while (last != NULL) {//将表头的所有临接点访问完,并入队,之后就不用访问表头了,出队后只要访问临接即可
if (visited[last->AdjV] == 0) {
V_squ.push_back(last->AdjV);
visited[last->AdjV] = 1;
visit_queue.push_back(last->AdjV);
}
last = last->next;
}
}
}
//深度优先遍历(输出)所有连通分量
void DFS_components(Graph *graph)
{
int visited[MAX_VERTEX];
for (int i = 0; i < graph->Vertex_num; i++)
visited[i] = 0;
for (Vertex i = 0; i < graph->Vertex_num; i++)
if (visited[i] == 0) {
DFS(graph, i, visited);
print_squ();
V_squ.clear();
}
}
void DFS(Graph *graph, Vertex first_V, int visited[])
{
AdjVNode *last;
Vertex V = first_V;
if (visited[V] == 0)
{
V_squ.push_back(V);
visited[V] = 1;
}
else return;
last = graph->G[V].first_node;
while (last != NULL)
{
V = last->AdjV;
DFS(graph, V, visited);
last = last->next;
}
}
void print_squ()
{
if (is_first_print)
is_first_print = 0;
else
cout << endl;
cout << "{ ";
while (!V_squ.empty())
{
cout << V_squ.front() << " ";
V_squ.pop_front();
}
cout << "}" ;
}
void sort_AdjV(Graph *graph)
{
AdjVNode *p;
for (Vertex i = 0; i < graph->Vertex_num; i++)
{
p = graph->G[i].first_node;
if (p) sort_bubble(p);
}
}
void sort_bubble(AdjVNode *head)
{
AdjVNode *p,*q;
AdjVNode *last;
last = NULL;
Vertex tmp;
while (head->next != last)
{
p = head;
q = p->next;
while (p->next != last)
{
if (p->AdjV > q->AdjV)
{
tmp = p->AdjV;
p->AdjV = q->AdjV;
q->AdjV = tmp;
}
p = p->next;
q = q->next;
}
last = p;
}
}