欧拉回路(上课要认真听)

欧拉回路

  欧拉回路是指不令笔离开纸面,可画过一个连通图中每条边仅一次
 ,且可以回到起点的一条回路。现给定一个图,问是否存在欧拉回路? 
写这个原因
 有次crq的课,我太困了,感觉讲的东西我会(那次刚开始课上讲的汉诺塔的递归),
 然后我就迷迷糊糊的睡过去了。等我醒来,讲的又是另外一个神奇的东西了,好像
 是关于DFS(deep fisrt search 深度优先搜索)。好家伙,上次课的欧拉回路(找师傅)   
 就听的迷迷糊糊,完了这回又是啥也没听了
解决方案

首先 用邻接矩阵(n*n),来构建图。不用下三角或三角压缩存储,有点麻烦。然后也不用邻接表,这个不知道图 疏不疏 ,而且邻接表对于这个题目操作也不方便。接着用广度优先搜索(BFS)从一个顶点去遍历,看能不能遍历完所有的顶点,即图连不连通.

欧拉回路的判断充要条件是:图为连通图,每个顶点的度为偶数

连通图
   任意连个顶点之间都存在路径,这个路径可以不是直达的,间接的也可以。
   本题是对无向图而言,如果是有向图的话,分为强连通图,弱连通图;
   路径就要标明方向 <Vstart,Vend>。这里就不展开了!
对于无向图而言,度表示,顶点的边数,而对于有向图而言,又分为出度和入度。
有向图的度等于出入度相加。

基本的理论说完了,开始写代码,我在把整体的代码主要分成三部分

  1. 图的创建和其相对应的基本操作
  2. 队列的创建和其相对应基本的操作
  3. 广度优先搜索 查找算法的实现
    提醒 最好在每个部分写完之后,就测试这部分的代码有没有出错。方便后面整体代码的调试。

我写的一遍就过了。(●ˇ∀ˇ●)

//==========================
//图的结构 
typedef struct {      //邻接矩阵 
	int VertexNum;   //定点数 
	int EdgeNum;     //边数
	int EdgeWeight[MaxNum][MaxNum];  //权重
	int Vertex[MaxNum];   //顶点的度数 
	int isTrav[MaxNum];   //保存遍历标志 
}GraphMatrix;
//图的初始化
void InitGraph(GraphMatrix *GM,int n,int m)
{
	GM->VertexNum=n;
	GM->EdgeNum=m;
	memset(GM->EdgeWeight,0,sizeof(GM->EdgeWeight));
	memset(GM->Vertex,0,sizeof(GM->Vertex));
}
//输入数据,造图
void CreatGraph(GraphMatrix *GM)
{
	int i,j,k;
	int Vstart,Vend;
	for(i=0;i<GM->EdgeNum;i++)
	{
		scanf("%d %d",&Vstart,&Vend);
		GM->EdgeWeight[Vstart][Vend]=1;
		GM->Vertex[Vstart]+=1;
		GM->EdgeWeight[Vend][Vstart]=1;
		//if(Vstart!=Vend)
		GM->Vertex[Vend]+=1;
	}	
}
//判断图的每个顶点度是否为偶数
int IsEven(GraphMatrix *GM)        //even 偶数
{
	int i,sum=0;
	for(i=1;i<=GM->VertexNum;i++)
	  sum+=GM->Vertex[i]%2;
	if(sum==0) return 1;
	else return 0;  
} 
//图的打印输出,测试图
void OutGraph(GraphMatrix *GM)
{
	int i,j;
	//输出顶点的信息
	printf(" ");
	for(i=1;i<=GM->VertexNum;i++)
	    printf(" %d",i);
	printf("\n");  
	for(i=1;i<=GM->VertexNum;i++)
	{ 
	  printf("%d ",i); 
	  for(j=1;j<=GM->VertexNum;j++)
	  {
	  	printf("%d",GM->EdgeWeight[i][j]);
	  	if(j!=GM->VertexNum)printf(" ");
	  }
	  printf("\n");
	}  
 }
//==========================

队列
这里 分为队列的主体代码部分,和测试代码部分

主体部分

//============================
typedef struct QNode{    //队列 
	int data;
	struct QNode *next;
}QNode,*QLink;
typedef struct{
	QLink first,rear;
}QNodeLink;
//初始化
void InitQueue(QNodeLink *Q)
{
	Q->first=(QLink)malloc(sizeof(QNode));
	Q->rear=Q->first;
	Q->first->next=NULL;
}
//判断队列是否为空
int IsEmpty(QNodeLink *Q)
{
	if(Q->first==Q->rear)
	return 1;
	else return 0;
}
//从队尾进队
void EnQueue(QNodeLink* Q,int x)
{
	QLink q=(QLink)malloc(sizeof(QNode));
	q->data=x;
	q->next=NULL;
	Q->rear->next=q;
	Q->rear=q;
}
//从队头,出队
void DeQueue(QNodeLink* Q,int *x)
{
	//int x;
	QLink q;
	if(!IsEmpty(Q))   //非空出队 
	{
	   q=Q->first;
	   Q->first=q->next;   //下个结点作为头结点 
	   *x=Q->first->data;
	   free(q);	
	}
	else printf("队列为空\n"); 
}
//销毁队列,养成好习惯,用完要还回去 
void DestoryQueue(QNodeLink *Q)
{
	int x;
	while(!IsEmpty(Q)) 
	 DeQueue(Q,&x);
	free(Q->first);
	free(Q); 
}

测试部分: 这个是很使用的,相当于模板,可以根据需要改。

int main()
{ 
    int x;
    char str[10];
    QNodeLink *Q=(QNodeLink *)malloc(sizeof(QNodeLink));
	InitQueue(Q);
	while(scanf("%s",str)!=EOF){
		if(!strcmp(str,"en"))
		{
			scanf("%d",&x);
			EnQueue(Q,x);
			printf("%d\n",Q->rear->data); 
		}
		else if(!strcmp(str,"de"))
		{
			if(IsEmpty(Q)) printf("队列为空!!!\n");
			else
			{
			   DeQueue(Q,&x);
			   printf("%d\n",x);
			} 
		}
		else if(!strcmp(str,"cls"))
		{
			system("cls");     //这个要包含头文件  #include<stdlib.h> 
		}
    }
    return 0; 
 }

广度优先搜索(BFS)

这部分要用到队列的思想,和二叉树顺序遍历有点像。
这里的话,我要用到 之前定义过的一个数组 Vertex[ ]来判断,这个顶点是否有没有被访问过,这样就可以减少代码的运行时间,减少资源的开销。
首先把第一个顶点入队,然后出队,访问它的边,这里是二维的数组EdgeWeight[ ][ ],看与之相邻的顶点是否有没有被访问过,如果没有被访问过则,入队。把入队的定标标记为已访问。重复上述操作,直至队列为空,详细看代码。

// 从一个点开始遍历,如果能找到所有的点就算,图连通,否则就不连通,广度优先搜素 
int BFS(GraphMatrix *GM)
{
	int x,i;
	QNodeLink *Q=(QNodeLink *)malloc(sizeof(QNodeLink));
	InitQueue(Q);
	//从1开始搜
	memset(GM->isTrav,0,sizeof(GM->isTrav));
	EnQueue(Q,1); 
	GM->isTrav[1]=1;
	while(!IsEmpty(Q))
	{ 	    
		DeQueue(Q,&x);
		for(i=1;i<=GM->VertexNum;i++)
		{
			if(i!=x&&GM->EdgeWeight[x][i]==1&&GM->isTrav[i]!=1)   //这里之前错了,0表示为没有访问过 
			{
				EnQueue(Q,i);
				GM->isTrav[i]=1;
			}
		}
	}
	DestoryQueue(Q);
	for(i=1;i<=GM->VertexNum;i++)
	  if(GM->isTrav[i]==0) return 0;
	return 1;  
}

完整的代码

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MaxNum 1000 
//========================== 
typedef struct {      //邻接矩阵 
	int VertexNum;   //定点数 
	int EdgeNum;     //边数
	int EdgeWeight[MaxNum][MaxNum];  //权重
	int Vertex[MaxNum];   //顶点的度数 
	int isTrav[MaxNum];   //保存遍历标志 
}GraphMatrix;
//==========================
typedef struct QNode{    //队列 
	int data;
	struct QNode *next;
}QNode,*QLink;
typedef struct{
	QLink first,rear;
}QNodeLink;
//==========================
void InitQueue(QNodeLink *Q)
{
	Q->first=(QLink)malloc(sizeof(QNode));
	Q->rear=Q->first;
	Q->first->next=NULL;
}
int IsEmpty(QNodeLink *Q)
{
	if(Q->first==Q->rear)
	return 1;
	else return 0;
}
void EnQueue(QNodeLink* Q,int x)
{
	QLink q=(QLink)malloc(sizeof(QNode));
	q->data=x;
	q->next=NULL;
	Q->rear->next=q;
	Q->rear=q;
}
void DeQueue(QNodeLink* Q,int *x)
{
	//int x;
	QLink q;
	if(!IsEmpty(Q))   //非空出队 
	{
	   q=Q->first;
	   Q->first=q->next;   //下个结点作为头结点 
	   *x=Q->first->data;
	   free(q);	
	}
	else printf("队列为空\n"); 
} 
void DestoryQueue(QNodeLink *Q)
{
	int x;
	while(!IsEmpty(Q)) 
	 DeQueue(Q,&x);
	free(Q->first);
	free(Q); 
}
void InitGraph(GraphMatrix *GM,int n,int m)
{
	GM->VertexNum=n;
	GM->EdgeNum=m;
	memset(GM->EdgeWeight,0,sizeof(GM->EdgeWeight));
	memset(GM->Vertex,0,sizeof(GM->Vertex));
}
void CreatGraph(GraphMatrix *GM)
{
	int i,j,k;
	int Vstart,Vend;
	for(i=0;i<GM->EdgeNum;i++)
	{
		scanf("%d %d",&Vstart,&Vend);
		GM->EdgeWeight[Vstart][Vend]=1;
		GM->Vertex[Vstart]+=1;
		GM->EdgeWeight[Vend][Vstart]=1;
		//if(Vstart!=Vend)
		GM->Vertex[Vend]+=1;
	}	
}
int IsEven(GraphMatrix *GM)        //even 偶数
{
	int i,sum=0;
	for(i=1;i<=GM->VertexNum;i++)
	  sum+=GM->Vertex[i]%2;
	if(sum==0) return 1;
	else return 0;  
} 
void OutGraph(GraphMatrix *GM)
{
	int i,j;
	//输出顶点的信息
	printf(" ");
	for(i=1;i<=GM->VertexNum;i++)
	    printf(" %d",i);
	printf("\n");  
	for(i=1;i<=GM->VertexNum;i++)
	{ 
	  printf("%d ",i); 
	  for(j=1;j<=GM->VertexNum;j++)
	  {
	  	printf("%d",GM->EdgeWeight[i][j]);
	  	if(j!=GM->VertexNum)printf(" ");
	  }
	  printf("\n");
	}  
 } 
// 从一个点开始遍历,如果能找到所有的点就算,图连通,否则就不连通,广度优先搜素 
int BFS(GraphMatrix *GM)
{
	int x,i;
	QNodeLink *Q=(QNodeLink *)malloc(sizeof(QNodeLink));
	InitQueue(Q);
	//从1开始搜
	memset(GM->isTrav,0,sizeof(GM->isTrav));
	EnQueue(Q,1); 
	GM->isTrav[1]=1;
	while(!IsEmpty(Q))
	{ 	    
		DeQueue(Q,&x);
		for(i=1;i<=GM->VertexNum;i++)
		{
			if(i!=x&&GM->EdgeWeight[x][i]==1&&GM->isTrav[i]!=1)   //这里之前错了,0表示为没有访问过 
			{
				EnQueue(Q,i);
				GM->isTrav[i]=1;
			}
		}
	}
	DestoryQueue(Q);
	for(i=1;i<=GM->VertexNum;i++)
	  if(GM->isTrav[i]==0) return 0;
	return 1;  
} 
int main()
{
	int n,m;
	int v1,v2;
	GraphMatrix *GM; 
	while(1)    //结点和边数 
	{
		scanf("%d",&n);
		if(n==0)break;
		scanf("%d",&m);
        GM=(GraphMatrix *)malloc(sizeof(GraphMatrix));
        InitGraph(GM,n,m);
        CreatGraph(GM);
		//OutGraph(GM);
		if(IsEven(GM)&&BFS(GM))
		printf("1\n");
		else printf("0\n");
		free(GM);
		//printf("偶数:%d 连通:%d\n",IsEven(GM),BFS(GM));         
	}
	return 0;
}
/*int main()
{ 
    int x;
    char str[10];
    QNodeLink *Q=(QNodeLink *)malloc(sizeof(QNodeLink));
	InitQueue(Q);
	while(scanf("%s",str)!=EOF){
		if(!strcmp(str,"en"))
		{
			scanf("%d",&x);
			EnQueue(Q,x);
			printf("%d\n",Q->rear->data); 
		}
		else if(!strcmp(str,"de"))
		{
			if(IsEmpty(Q)) printf("队列为空!!!\n");
			else
			{
			   DeQueue(Q,&x);
			   printf("%d\n",x);
			} 
		}
		else if(!strcmp(str,"cls"))
		{
			system("cls");     //这个要包含头文件  #include<stdlib.h> 
		}
    }
    return 0; 
 }
 */

这部分代码可以过题。TZOJ 题号为:3649
请勿直接复制,提交。做人要讲武德┗|`O′|┛ 嗷~~

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值