求无向图两个顶点之间长度等于k的所有简单路径(C语言)

【问题描述】在无向图的邻接表存储结构上实现:求两个顶点之间的所有长度等于k的简单路径

【样例输入】6 8 abcdef a b a c b d b f c f c e d f e f a f 3

  解释:无向图顶点个数6,边的个数8,顶点序列:abcdef,边(a b)(a c)(b d)(b f)(c f)(c e)(d f )(e f),两个顶点和k:a f 3
【样例输出】

    a b d f

    a c e f

//难度:3
//要求:在无向图的邻接表存储结构上实现:判断任意给定的两个顶点之间是否存在一条长度等于k的简单路径

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stddef.h>
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
#define LIST_INIT_SIZE 100
#define STACK_INIT_SIZE 100
typedef int Status;


#define MAX_VERTEX_NUM 20
typedef enum {DG,DN,AG,AN} GraphKind;//有向图、有向网、无向图、无向网
typedef struct ArcNode{
	int	adjvex;					//该弧头的位置
	struct ArcNode *nextarc;	//下一条出弧(弧尾相同的下一条弧)
	int		info;				//附加信息
}ArcNode;	//弧结点

typedef char VertexType ;
typedef struct VNode{
	VertexType data;			//顶点信息
	ArcNode *firstarc;	//第一条出弧
}VNode, AdjList[MAX_VERTEX_NUM];	//邻接表头指针向量

typedef struct {
	AdjList vertices;		//邻接表头指针向量
	int vexnum,arcnum;		//顶点数目和弧的数目
	GraphKind kind;			//图的种类
}ALGraph;

//返回顶点u在图中的位置,未找到返回-1
int LocateVex(ALGraph G,VertexType u)
{	int i;
	for(i = 0; i < G.vexnum; i++)
		if(G.vertices[i].data == u) return i;
	return -1;
} 

//创建无向图
void CreateAG(ALGraph &G)
{	int i,j,k,info = 0;
	VertexType v1,v2;
	ArcNode * p;
    
//	printf("\n下面分步输入创建无向图的信息:"); G.kind = AG;
//	printf("\n1.请输入图的顶点个数:"); 	
        scanf("%d", &G.vexnum);
//      printf("\n2.请输入图的边的个数:"); 	
        scanf("%d", &G.arcnum);
//	printf("\n3.请连续输入%d个顶点(字符型):",G.vexnum);
	scanf("%c",&G.vertices[0].data);	//滤掉换行字符
//	printf("n=%d e=%d",G.vexnum,G.arcnum);
        for(k = 0; k < G.vexnum; k++)	//邻接表头指针向量初始化
	  {	scanf("%c", &G.vertices[k].data);
		G.vertices[k].firstarc = NULL; 
	  }
        
//        for(k = 0; k < G.vexnum; k++)	//邻接表头指针向量初始化
//	    printf("%d=%c " , k,G.vertices[k].data);
	 
	for(k = 0; k < G.arcnum; k++)		//建立弧结点<v,w>
          {   //printf("\n建立弧%d,请输入弧的信息,格式为v,w:",k+1); 
	        scanf("%c",&v1);	//滤掉换行字符
		scanf("%c %c", &v1, &v2);
		i = LocateVex(G,v1); j = LocateVex(G,v2);	//确定v1,v2在图中的位置
		if(i == -1 || j == -1)
			{ printf("\n输入弧信息非法,程序退出!%c %c %d %d  ",v1, v2,i,j); break; }

                p = (ArcNode *) malloc( sizeof(ArcNode) );
		p->adjvex = j; 
		p->info = info;
		p->nextarc = G.vertices[i].firstarc;
		G.vertices[i].firstarc = p; 

                p = (ArcNode *) malloc( sizeof(ArcNode) );
		p->adjvex = i; 
		p->info = info;
		p->nextarc = G.vertices[j].firstarc;
		G.vertices[j].firstarc = p; 
         }
}

//按邻接表的形式输出无向图
void PrintAG(ALGraph G)
{	ArcNode *p;
	printf("\n无向图G的邻接表形式:");
	for(int i = 0; i < G.vexnum; i++)
	{	printf("\n %c",G.vertices[i].data);
		if( G.vertices[i].firstarc )
		{	printf("-->");
			for(p = G.vertices[i].firstarc; p; p = p->nextarc)
			{	printf("%c",G.vertices[p->adjvex].data);
				if(p->nextarc) printf("-->");
			}
		}
	}
	printf("\n");
}

//返回v(顶点位置)的第一个邻接顶点的位置,若无返回-1
int FirstAdjVex(ALGraph G, int v)
{	ArcNode *p;
	p = G.vertices[v].firstarc;
	if(p) return p->adjvex;
	else return -1;
}

//返回v相对于w(顶点位置)的下一个邻接顶点的位置,若无返回-1
int NextAdjVex(ALGraph G, int v, int w)
{	ArcNode *p;
	for(p = G.vertices[v].firstarc; p->nextarc; p = p->nextarc)
		if(p->adjvex == w) return p->nextarc->adjvex;
	
	return -1;
}
//level表明当前递归调用的层次,也即v,j的路径长度
//此算法遍历全部v->j的路径,直到找到长度为k的为止
VertexType Path[MAX_VERTEX_NUM];
int p;
int visited[MAX_VERTEX_NUM];
void DFS(ALGraph G,int v,int j,int k,int level)
{	int w;
	//若v未被访问或被访问了又删除了访问记录
	if(!visited[v]){
	  visited[v]=1;
	  //将当前访问的节点v置为当前路径上一个新的节点
	  Path[p++]=G.vertices[v].data;
	 //若满足条件则输出路径
	  if((v==j) && ((k+1)==level)){
	  for(int i=1;Path[i]!='\0';i++)
	    {printf("%c ",Path[i]);}
	  printf("\n");
	  }
	  else{
	  //从v的邻接点出发探索
	  w=FirstAdjVex(G,v);
	 //若邻接点存在
	  while(w!=-1){
	  //递归调用函数,level值加一
	  DFS(G,w,j,k,level+1); 
	  //从v相对于w的下一个邻接顶点出发探索
	  w=NextAdjVex(G,v,w); 
	    }
	  }
	  //删除访问记录
	  visited[v]=0;
	  //把当前节点v从当前路径上删除
	  p--;
	  Path[p]='\0';
	}

}

//判断vi->vj是否有长度为k的简单路径

void PathDFS(ALGraph G,VertexType vi,VertexType vj,int k)
{	int i,j;
	for(i = 0; i < G.vexnum; i++) visited[i] = 0;	//初始化顶点访问标志
	p = 0;
	i = LocateVex(G,vi); j = LocateVex(G,vj);	//确定vi,vj在图中的位置
	if(i == -1 || j == -1)
		{ printf("\n输入顶点信息非法,程序退出!"); return ; }
	
	Path[p++] = G.vertices[i].data;
	DFS(G,i,j,k,1);	//从i出发深度优先搜索
}

int main()
{	
    int k;
    VertexType vi,vj;
	
    ALGraph G;
    CreateAG(G); 
    // PrintAG(G); 

    //printf("\n判断是否存在由vi到vj的长度为k的简单路径,请输入vi、vj和k:");
    scanf("%c",&vi);
    scanf("%c %c %d",&vi,&vj,&k);
    PathDFS(G,vi,vj,k);
    printf("\n");
    return OK;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值