给定一个有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 }
以下是AC答案:
#include<stdio.h>
#include<stdlib.h>
#define max_n 10
typedef int ElementType;
typedef struct mGraph* ptrtomgraph;
int visited[max_n];
struct mGraph{//邻接矩阵图的定义
int Nv;
int Ne;
ElementType G[max_n][max_n];
};
typedef ptrtomgraph mgraph;
typedef struct _edge* ptrtoedge;
struct _edge{//边的定义
int a,b;
//int weight;
};
typedef ptrtoedge edge;
struct queue{
int front,rear;
int* Q[max_n];
}q={-1,-1};
void addqueue(int v);
int deletequeue();
mgraph creatgraph(mgraph g);
edge inputedge(edge e);
void initiatevisited();
void DFS(mgraph g,int i);
void BFS(mgraph g,int i);
int main(){
mgraph G;
G=(mgraph)malloc(sizeof(struct mGraph));
G=creatgraph(G);
initiatevisited();
for(int i=0;i<G->Nv;i++){
if(!visited[i]){
printf("{ ");
DFS(G,i);
printf("}\n");
}
}
initiatevisited();
for(int i=0;i<G->Nv;i++){
if(!visited[i]){
printf("{ ");
BFS(G,i);
printf("}\n");
}
}
return 0;
}
void BFS(mgraph g,int v){
printf("%d ",v);
visited[v]=1;
addqueue(v);
int vi;
while(q.rear!=q.front){
vi=deletequeue();
for(int i=0;i<g->Nv;i++){
if(g->G[vi][i]==1&&!visited[i]){
printf("%d ",i);
visited[i]=1;
addqueue(i);
}
}
}
}
void DFS(mgraph g,int v){
visited[v]=1;
printf("%d ",v);
for(int i=0;i<g->Nv;i++){
if(g->G[v][i]==1&&!visited[i]){
DFS(g,i);
}
}
}
mgraph creatgraph(mgraph g){
int nv,ne;
edge e=(edge)malloc(sizeof(struct _edge));
scanf("%d %d",&nv,&ne);
g->Nv=nv;
g->Ne=ne;
for(int i=0;i<nv;i++)
for(int j=0;j<nv;j++)
g->G[i][j]=0;
for(int i=0;i<ne;i++){
e=inputedge(e);
g->G[e->a][e->b]=1;
g->G[e->b][e->a]=1;
}
/*for(int i=0;i<nv;i++){
for(int j=0;j<nv;j++)
printf("%d ",g->G[i][j]);
printf("\n");
}*/
return g;
}
edge inputedge(edge e){
scanf("%d %d",&(e->a),&(e->b));
return e;
}
void initiatevisited(){
for(int i=0;i<max_n;i++){
visited[i]=0;
}
}
void addqueue(int v){
q.Q[++q.rear]=v;
}
int deletequeue(){
return q.Q[++q.front];
}
尝试使用半个邻接矩阵的空间解决问题,但是并没有成功。只能在类似题目给出的例子的情况下才能正确。而当三角形矩阵的前面列没有与后一列的相连时(比如陈越主编的数据结构这本教材给出的例子,1和3相连,2和3相连时,此程序会错误略过2,导致2和他之后的没有被打印的数字单独成一个连通集。并且,相较于正方形的邻接矩阵,结果打印的顺序有所不同。半邻接矩阵的存储方法的尝试以失败告终。
在写下完整邻接矩阵的深度遍历后,我有思考尝试用横竖列交替遍历这一半邻接矩阵的方法,但是并不能达到深度优先的输出效果。尝试用折线阶梯遍历的方法再开始尝试时就毫无头绪,阶梯遍历似乎没有一个合适的条件进行转弯?也许应该在更加熟悉DFS过后才能给出是否可行的明确答案。
以下是无法完全通过第二个测试点的半邻接矩阵实现:
#include<stdio.h>
#include<stdlib.h>
#define max_n 10
#define max_matrixN 55//n(n+1)/2
typedef struct queue Q;
struct queue{
int *q;
int front,rear;
}q;
void initializeG(int* g,int n);
void connectV(int* g){
int a,b,i,j;
scanf("%d %d",&a,&b);
i=a>b?a:b;
j=a<b?a:b;
g[i*(i+1)/2+j]=1;
}
void DFS(int *g,int n,int i);
void BFS(int *g,int n,int i);
void initializeCnt(int *c,int N);
void addqueue(int i){
if(q.rear==max_n-1){
printf("队满\n");return;
}
q.q[++q.rear]=i;
}
int deletequeue(){
if(q.rear==q.front){
printf("队空\n");return -1;
}
int k;
k=q.q[++q.front];
return k;
}
int main(){
int N,E;
int G[max_matrixN];
scanf("%d %d",&N,&E);
int n=N*(N+1)/2;
initializeG(G,n);
for(int i=0;i<E;i++){
connectV(G);
}
for(int i=0,count=1,k=0;i<n;i++){//调试用
printf("%d ",G[i]);
k++;
if(k==count){
printf("\n");
k=0;
count+=1;
}
}
int i;
for(i=0;i<N;i++){
if(!G[i*(i+1)/2+i]){
printf("{");
DFS(G,N,i);
printf(" }\n");
}
}
initializeCnt(G,N);
q.q=(int*)malloc(max_n*sizeof(int));
q.front=q.rear=-1;
for(int i=0;i<N;i++){
if(!G[i*(i+1)/2+i]){
BFS(G,N,i);
}
}
return 0;
}
void DFS(int *g,int N,int i){
int j=i;
printf(" %d",i);
g[i*(i+1)/2+i]--;
for(;i<N;i++){
if(g[i*(i+1)/2+j]==1){//对每一列从上到下进行遍历查找边
if(!g[i*(i+1)/2+i]){//查找到第j列的第i行为1,判断i是否打印过
DFS(g,N,i);//按深度,对第i列进行遍历,查找与i相连的边。
}
}
}
}
void BFS(int *g,int N,int i){
printf("{ %d ",i);
addqueue(i);
g[i*(i+1)/2+i]--;
while(q.front!=q.rear){
int i=deletequeue(),j=i;
for(i+=1;i<N;i++){
if(g[i*(i+1)/2+j]==1&&!g[i*(i+1)/2+i]){
g[i*(i+1)/2+i]--;
printf("%d ",i);
addqueue(i);
}
}
}
printf("}\n");
}
void initializeCnt(int *g,int N){
for(int i=0;i<N;i++){
g[i*(i+1)/2+i]=0;
}
}
void initializeG(int* c,int n){
for(int i=0;i<n;i++){
c[i]=0;
}
}