讨论四:图的应用——构造最小生成树

构造最小生成树

内容要点

某省自从实行了畅通工程计划后,终于修建了很多道路。不过路多了也不好,每次要从一个城镇到另一个城镇时,都有许多种道路方案可以选择,而某些方案要比另一些方案行走的距离要短很多。这让行人很困扰。现在请你设计程序计算出要使这些城镇互通的最小路径长度。

实验目的

掌握图的邻接矩阵表示法;
掌握无向图的最小生成树算法(prim和kruskal);
运用最小生成树算法解决实际问题;

实验内容及要求

本题目包含多组输入数据
每组数据的第一行包含两个正整数N和M(0<N<200,0<M<1000),分别代表现有的城镇数目和已修建的道路数目。城镇分别以0~N-1编号。(当输入N或M为0时结束)
接下来是M行道路信息。每行有三个整数A,B,X(0<=A,B<N;A!=B;0<X<10000),分别表示城镇A,城镇B,以及城镇A与B之间有一条长度为X的双向道路。
对每组输入数据,利用prim算法或者kruskal算法构建相应的最小生成树,并输出连接这些城镇的最小路程。
如果不存在最小生成树,则输出-1;

代码(prim)


详解已备注在代码中

#include<iostream>//构造最小生成树
#include<iomanip>
using namespace std;
#define nn 200//假定最多200个顶点
class AddArray
{
public:
	int adjvex;
	//记录生成树集合外V-U各顶点距离集合内U哪个顶点权值最小
	int lowcost;
	//生成树外各顶点V-U到生成树U集合内顶点的各边的当前最小权值
};
class Graph
{
public:
	int vertex[nn];//储存顶点的数组
	int arc[nn][nn];//储存边的二维数组
	void creat(int n,int e)//邻接矩阵构造无向图//n顶点数,e边数
	{
		/初始化
		for(int i=0;i<n;i++)
		{
			for(int j=0;j<n;j++)
			{
				if(i==j)
					arc[i][j]=0;
				else
					arc[i][j]=999;
			}
		}
		///将顶点信息和边的信息存入数组
		for(int i=0;i<n;i++)
		{
			
			vertex[i]=i;//城镇以0~n-1编号
		}
		cout<<endl;
		int vi,vj,w;
		for(int i=0;i<e;i++)
		{
			cout<<"请输入边的信息,i,j,w(城镇以0~n-1编号,w为权值):";
			cin>>vi>>vj>>w;
			arc[vi][vj]=w;
			arc[vj][vi]=w;//无向图具有对称性
		}
	}
	void show(int n,int e)//输出邻接矩阵的信息
	{
		cout<<endl<<"输出顶点的信息(int):"<<endl;
		for(int i=0;i<n;i++)
			cout<<vertex[i]<<' ';
		
		cout<<endl<<"输出邻接矩阵:"<<endl;
		for(int i=0;i<n;i++)
		{
			for(int j=0;j<n;j++)
			{
				if(arc[i][j]==999)
					cout<<setw(5)<<"∞"<<' ';
				else
					cout<<setw(5)<<arc[i][j]<<' ';
			}
			cout<<endl;
		}
	}
	void prim(int n)//最小生成树
	{
		AddArray hhh[200];
		int sum=0;//最小生成树的路程长度
		hhh[0].adjvex=0;
		hhh[0].lowcost=0;
		for(int i=1;i<n;i++)
		{
			hhh[i].lowcost=arc[0][i];//lowcost初始化为邻接矩阵第一行的权值
			hhh[i].adjvex=0;//adj全部存放下标为0的顶点
		}
		//

		//找到第i行权值最小的边的下标
		cout<<endl<<endl;
		for(int i=1;i<n;i++)
		{
			int min=999;//先初始化为999,表示无连接
			int k=0;//k为权值最小的边的终点
			for(int j=1;j<n;j++)
			{
				//找到第i行权值最小的边,记录终点的下标
				if(hhh[j].lowcost!=0&&hhh[j].lowcost<min)
				{
					min=hhh[j].lowcost;
					k=j;
				}
			}
			hhh[k].lowcost=0;
			if(hhh[k].adjvex==k)//没有最小生成树的情况
			{
				cout<<"-1"<<endl;return;
			}
			
			///打印当前顶点中权值最小的边
			cout<<"("<<vertex[hhh[k].adjvex]<<","<<vertex[k]<<")"<<endl;
			//求最短路径长度
			sum+=arc[hhh[k].adjvex][k];
			///遍历第k行的所有权值
			for(int j=1;j<n;j++)
			{
				if(hhh[j].lowcost!=0&&arc[k][j]<hhh[j].lowcost)
				{
					hhh[j].lowcost=arc[k][j];
					hhh[j].adjvex=k;
				}
			}
		}
		cout<<"最小生成树的路程长度为:"<<sum<<endl;
	}
};
int main()
{
	Graph G;int n,m;
	cout<<"输入城镇数量或道路数量为零时退出"<<endl<<endl;
	cout<<"请输入城镇数量:";cin>>n;cout<<endl;//城镇数量
	if(n==0) 
		m=0;
	else
	{
		cout<<"请输入道路数量:";cin>>m;cout<<endl;
	}
	while(n&&m)//多组数据输入
	{
		G.creat(n,m);//邻接矩阵构造无向带权图
		G.show(n,m);//输出图的相关信息
		G.prim(n);
		cout<<endl;
		cout<<"输入城镇数量或道路数量为零时退出"<<endl<<endl;
		cout<<"请输入城镇数量:";cin>>n;cout<<endl;//城镇数量
		if(n==0)
			m=0;
		else
		{
			cout<<"请输入道路数量:";cin>>m;cout<<endl;
		}
	}
}

作者自述

这篇整理可用了太多的时间,你们的鼓励是支持作者的无尽动力源泉!给作者一个小赞吧!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

纸梯先生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值