浙江大学数据结构MOOC-课后习题-第八讲-图7 公路村村通

题目汇总
浙江大学数据结构MOOC-课后习题-拼题A-代码分享-2024

题目描述

在这里插入图片描述

思路分析

本题要求每个村落都有公路连通,且成本最低。它的实质是求最小生成树
由题目描述可知,构成的图为稠密图,因此采用Prim算法

值得注意的地方
当边数Ne < 顶点数Nv - 1时,此时是一个非连通图,是无法构成最小生成树的,因此对这种情况单独进行判断

我在解题时遇到的一个问题是,如果我在调用buildGraph()创建好图后,再来判定是否有Ne < Nv - 1,此时我是无法得出正确答案的(但我不知道这是为什么…sad

因此,我将该判断语句放在了buildGraph()函数内部执行,根据buildGraph()的返回值来判断是否连通。

代码展示

/*
	本题要求每个村落都有公路连通,且成本最低。它的实质是求最小生成树
	本题先采用Prim算法:使用稠密图,类似于Dijkstra算法
*/
#include <cstdlib>
#include <iostream>
#define MAXSIZE 1000
#define INFINITY 65535
#define ERROR 65535
typedef int vertex;
typedef int weightType;
/* 边节点 */
struct ENode
{
	vertex V1, V2;
	weightType cost;
};
typedef ENode* ptrToENode;
typedef ptrToENode Edge;
/* 图 */
struct GNode
{
	int Ne; /* 边数 */
	int Nv; /* 顶点数 */
	weightType G[MAXSIZE][MAXSIZE];	/* 数组下标比实际编号小1 */
};
typedef GNode* ptrToGNode;
typedef ptrToGNode MGraph;
/* 插入边 */
void insertEdge(MGraph Graph, Edge E)
{	/* 数组下标比实际编号小1 */
	Graph->G[E->V1 - 1][E->V2 - 1] = E->cost;
	Graph->G[E->V2 - 1][E->V1 - 1] = E->cost;
}
/* 创建并初始化图 */
MGraph creatGraph(int Nv)
{
	MGraph Graph = (MGraph)malloc(sizeof(GNode));
	Graph->Nv = Nv;
	Graph->Ne = 0;
	for (vertex V = 0; V < Graph->Nv; V++)
	{
		for (vertex W = 0; W < Graph->Nv; W++)
		{	
			Graph->G[V][W] = INFINITY;
		}
	}
	return Graph;
}
/* 构造完整的图 */
MGraph buildGraph()
{
	int Nv, Ne;
	std::cin >> Nv >> Ne;
	if (Ne < Nv - 1)
		return NULL;
	MGraph Graph = creatGraph(Nv);
	Graph->Ne = Ne;
	/* 读取并插入边 */
	Edge E = (Edge)malloc(sizeof(ENode));
	for (int i = 0; i < Graph->Ne; i++)
	{
		std::cin >> E->V1 >> E->V2 >> E->cost;
		insertEdge(Graph, E);
	}
	return Graph;
}
vertex getMinDist(MGraph Graph, int dist[])
{
	vertex minV;
	int minDist = INFINITY;
	for (vertex V = 0; V < Graph->Nv; V++)
	{	/* 还未被收录 */
		if (dist[V] != 0)
		{
			if (dist[V] < minDist)
			{
				minV = V;
				minDist = dist[V];
			}
		}
	}
	if (minDist != INFINITY)
		return minV;
	else return ERROR;
}
bool Prim(MGraph Graph, int dist[], int parent[], vertex S)
{	
	vertex V, W;
	int count = 0; /* 计数收入树中的顶点个数 */
	/* 初始化 */
	for(V = 0; V < Graph->Nv; V++)
	{	
		dist[V] = Graph->G[S][V];
		if (dist[V] == INFINITY)
			parent[V] = -1;
		else
			parent[V] = S;
	}
	/* 将源点收入树中 */
	dist[S] = 0;
	parent[S] = -1;
	count++;
	while (1)
	{	
		V = getMinDist(Graph, dist);
		if (V == ERROR)
			break;
		/* 将V收录进树中 */
		dist[V] = 0;
		count++;
		/* 遍历V的所有邻接点 */
		for (W = 0; W < Graph->Nv; W++)
		{
			if (Graph->G[V][W] != INFINITY)
			{
				if (dist[V] + Graph->G[V][W] < dist[W])
				{
					dist[W] = dist[V] + Graph->G[V][W];
					parent[W] = V;
				}
			}
		}
	}
	/* 当结束while循环会有两种情况:1、已经实现最小生成树 2、最小生成树不连通 */
	if (count < Graph->Nv)
	{
		return false;
	}
	return true;
}

int main()
{	
	int dist[MAXSIZE];
	int parent[MAXSIZE];
	int sum = 0;
	vertex S, V, W;
	MGraph Graph = buildGraph();
	/* 先判断能否满足最小生成树顶点和边的关系 */
	if(Graph == NULL)
	{
		std::cout << "-1";
		return 0;
	}

	/* 利用Prim求最小生成树,此处令村庄1作为树的根节点 */
	S = 0;
	if (!Prim(Graph, dist, parent, S))
	{
		std::cout << "-1";
		return 0;
	}

	/* 求最低成本 */
	for (V = 0; V < Graph->Nv; V++)
	{
		if(V != S)
		{	
			W = parent[V];
			sum += Graph->G[V][W];
		}
	}
	std::cout << sum;
	return 0;
}

心路历程

对于dist的初始化真的傻傻分不清,什么情况初始化为什么值了解得还不够透彻…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值