Discussion 4: Application of graphs-construction of minimum spanning tree

Construct minimum spanning tree

Content highlights

A province has finally built many roads since the implementation of the smooth flow project plan. However, it is not good to have more roads. Every time you want to travel from one town to another, there are many road plans to choose from, and some plans have a much shorter distance than others. This bothers pedestrians. Now please design a program to calculate the minimum path length that will allow these towns to communicate.

Purpose

Master the adjacency matrix representation of graphs;
master the minimum spanning tree algorithm (prim and kruskal) of undirected graphs;
use the minimum spanning tree algorithm to solve practical problems;

Experiment content and requirements

This question contains multiple sets of input data
. The first row of each set of data contains two positive integers N and M (0<N<200, 0<M<1000), which represent the number of existing towns and the number of roads built. The towns are numbered from 0 to N-1. (End when input N or M is 0)
Next is the road information of M lines. Each line has three integers A, B, X (0<=A,B<N;A!=B;0<X<10000), which represent town A, town B, and a length between town A and B The two-way road for X.
For each set of input data, use the prim algorithm or kruskal algorithm to construct the corresponding minimum spanning tree, and output the minimum distance connecting these towns.
If there is no minimum spanning tree, output -1;

Code (prim)


The detailed explanation has been noted in the code

#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;
		}
	}
}

Author's Statement

Too much time has been used for this compilation, and your encouragement is an endless source of motivation to support the author! Give the author a thumbs up!

Guess you like

Origin blog.csdn.net/qq_43704702/article/details/104029671
Recommended