题目 A3:有向图的简单路径求解问题给定一个有向图 G 两个顶点 a和 b,试编写算法求a到b的简单路径的数量,并分别输出最短的简单路径和最长的简单路径

题目 A3:有向图的简单路径求解问题
给定一个有向图 G 两个顶点 a和 b,试编写算法求a到b的简单路径的数量,并分别输出最短的简单路径和最长的简单路径

 


#define PATH_HEADER_
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#define ERROR 0
#define OK 1
#define Overflow 2   //Overflow表示上溢出
#define Underflow 3   //Underflow表示下溢出
#define NotPresent 4  //NotPresent表示元素不存在
#define Duplicate 5     //Duplicate 表示有重复的元素
#define STLEN 5
static int sum = 0;  //统计有几条简单路径
static int min_number = 100;  //假设此图最多包含100个顶点
typedef int Status;
typedef int ElemType;
typedef struct eNode
{
	int adjVex;   //与任意顶点u相邻接的顶点
	ElemType w;     //边的权值
	struct eNode* nextArc;  //指向下一个边节点
}ENode;
typedef struct lGraph
{
	int n;      //图的当前顶点数
	int e;          //图的当前边数
	ENode **a;      //指向一维指针数组
}LGraph;
Status Init(LGraph *lg, int nSize);
void Destroy(LGraph *lg);
Status Exist(LGraph *lg, int u, int v);
Status Insert(LGraph *lg, int u, int v,ElemType w); 
Status Remove(LGraph *lg, int u, int v);
void DFS(int v, int length, int visited[],LGraph *Lg);
void DFSGraph(LGraph *Lg);
int min = INT_MAX;
int max = INT_MIN;


void Destroy(LGraph *lg)
{
	ENode *p, *q;
	for (int i = 0; i < lg->n; i++)
	{
		p = lg->a[i];
		q = p;
		while (p)
		{
			p = p->nextArc;
			free(q);
			q = p;
		}
	}
	free(lg->a);
}


Status Exist(LGraph *lg, int u, int v)
{
	ENode *p;
	if (u < 0 || v < 0 || u > lg->n - 1 || v > lg->n - 1 || u == v)
	{
		return ERROR;
	}
	p = lg->a[u];
	while (p && p->adjVex != v)
	{
		p = p->nextArc;
	}
	if (!p)
	{
		return ERROR;
	}
	else
	{
		return OK;
	}
}

Status Insert(LGraph *lg, int u, int v, ElemType w)
{
	ENode *p;
	if (u < 0 || v < 0 || u > lg->n - 1 || v > lg->n - 1 || u == v)
	{
		return ERROR;
	}
	if (Exist(lg, u, v))
	{
		return Duplicate;
	}
	p = (ENode *)malloc(sizeof(ENode *)); //为新的节点分配内存
	p->adjVex = v;
	p->w = w;
	p->nextArc = lg->a[u]; //将新的边节点插入单链表的最前面
	lg->a[u] = p;
	lg->e++;
	return OK;
}

Status Remove(LGraph *lg, int u, int v)
{
	ENode *p, *q;
	if (u < 0 || v < 0 || u > lg->n - 1 || v > lg->n - 1 || u == v)
	{
		return ERROR;
	}
	p = lg->a[u], q = NULL;
	while (p && p->adjVex != v)
	{
		q = p;
		p = p->nextArc;
	}
	if (!p)
	{
		return NotPresent; //p为空,待删除边不存在
	}
	if (q)
	{
		q->nextArc = p->nextArc; //从单链表删除此边
	}
	else
	{
		lg->a[u] = p->nextArc; //此时为第一个边节点就是待删除边的情况
	}
	free(p);
	lg->e--;
	return OK;
}


void DFS(int v, int length, int visited[], int path[], LGraph *Lg, int* count) {
	
	for (p = Lg->a[v]; p; p = p->nextArc) {
		if (!visited[p->adjVex] && p) {
			visited[p->adjVex] = 1;
			path[length + 1] = p->adjVex; // 将经过的顶点添加到路径中
			DFS(p->adjVex, length + 1, visited, path, Lg, count);
			visited[p->adjVex] = 0;
		}
	}
}


int main()
{
	LGraph Lg;  //声明一个图,名字为Lg
	int n;  //此图顶点的个数
	printf("请输入需要此图需要的顶点数:");
	scanf("%d",&n);
	getchar();
	int status = Init(&Lg, n);  //初始化图,为每个顶点分配内存空间,初始化成功,status为1,反之返回0
	if(!status)
	{
		printf("没有成功动态生成长度为%d的一维指针数组,程序终止运行!\n\n",n);
	}
	else
	{
		printf("带有%d个顶点的图已经初始化完成,请插入边<u,v>及权值w,以构成完整的图\n\n",n);
	}
	int u, v, w;   //表示顶点u、v和权值w
	int i = 1;  //统计第几条边
	char flag[5];//接收输入
	printf("是否准备为初始化的图插入边(yes/no):");
	gets(flag);
	while(strcmp(flag, "yes") == 0)
	{
		printf("请插入第%d条边<u,v>及权值w:",i);
		scanf("%d %d %d",&u,&v,&w);
		getchar();
		status = Insert(&Lg, u, v, w);  //检查插入操作是否成功
		if(status == 5)  
		{
			printf("您输入的顶点已存在,请重新输入!\n\n");
			continue;
		}
		else if(status == 0)
		{
			printf("参数u=%d、v=%d无效,请重新输入!\n\n",u, v);
			continue;
		}
		else
		{
			printf("第%d条边已经成功插入完成!\n\n",i);
		}
		i++;  //为即将插入的边做好准备
		printf("是否继续插入边(yes/no):");
		gets(flag);  //接收输入
		if(strcmp(flag, "yes") != 0)
		{
			printf("带有%d个顶点的图一共成功插入%d条边\n\n",n, i-1);
			break;
		}
	}
	int m = i-1;   //为了统计还剩下几条边
	printf("是否错误插入某条边,请删除!(yes/no):");
	gets(flag);
	i = 1;
	while(strcmp(flag, "yes") == 0)
	{
		printf("请输入要删除第%d条边<u,v>:",i);
		scanf("%d %d",&u,&v);
		getchar();
		status = Remove(&Lg, u, v);  //调用remove操作,返回删除操作的状态
		if(status == 4)
		{
			printf("您输入的顶点不存在,请重新输入!\n\n");
			continue;
		}
		else if(status == 0)
		{
			printf("参数u=%d、v=%d无效,请重新输入!\n\n",u, v);
			continue;
		}
		else
		{
			printf("第%d条边已经成功删除完成!\n\n",i);
		}
		i++;//为继续删除边做好准备
		printf("是否继续删除边(yes/no):");
		gets(flag);
		if(strcmp(flag, "yes") != 0)
		{
			printf("带有%d个顶点的图一共删除了%d条边,还剩下%d条边\n\n",n, i-1, m-(i-1));
			break;
		}
	}
	
	Destroy(&Lg);  //释放内存空间
	return 0;
}

代码不完整,欢迎交流 需要完整代码联系我:维新:lxt123ljh456

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,我可以给您提供一个简单的 Python 代码来实现B的矩阵表示以及计算长度不超过4的路条数。 首先,我们需要定义一个邻接矩阵的二维数组,并将其初始化为0。然后,我们可以过读取有向图的边来更新邻接矩阵。具体来说,如果有一条由节点i指向节点j的有向边,则邻接矩阵中A[i][j]的值为1。 接下来,我们可以过邻接矩阵来计算入度矩阵和出度矩阵。具体来说,入度矩阵中D[i][i]的值表示节点i的入度,即与节点i相连的入边数;而出度矩阵中D[i][i]的值表示节点i的出度,即与节点i相连的出边数。 最后,过矩阵乘法可以计算出长度不超过4的路条数矩阵B。具体来说,我们可以先计算A^2、A^3、A^4的值,然后将它们相加得到B矩阵。 下面是示例代码,假设有向图的边保存在一个列表edges中,节点数为n: ```python # 初始化邻接矩阵 A = [[0] * n for _ in range(n)] # 更新邻接矩阵 for i, j in edges: A[i][j] = 1 # 计算入度矩阵 D_in = [[0] * n for _ in range(n)] for i in range(n): D_in[i][i] = sum(A[j][i] for j in range(n)) # 计算出度矩阵 D_out = [[0] * n for _ in range(n)] for i in range(n): D_out[i][i] = sum(A[i][j] for j in range(n)) # 计算长度不超过4的路条数矩阵 A2 = [[0] * n for _ in range(n)] for i in range(n): for j in range(n): A2[i][j] = sum(A[i][k] * A[k][j] for k in range(n)) A3 = [[0] * n for _ in range(n)] for i in range(n): for j in range(n): A3[i][j] = sum(A2[i][k] * A[k][j] for k in range(n)) A4 = [[0] * n for _ in range(n)] for i in range(n): for j in range(n): A4[i][j] = sum(A3[i][k] * A[k][j] for k in range(n)) B = [[A[i][j] + A2[i][j] + A3[i][j] + A4[i][j] for j in range(n)] for i in range(n)] ``` 以上代码中,B矩阵即为长度不超过4的路条数矩阵,B[i][j]表示从节点i到节点j的长度不超过4的路条数。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值