构造最小生成树
内容要点
某省自从实行了畅通工程计划后,终于修建了很多道路。不过路多了也不好,每次要从一个城镇到另一个城镇时,都有许多种道路方案可以选择,而某些方案要比另一些方案行走的距离要短很多。这让行人很困扰。现在请你设计程序计算出要使这些城镇互通的最小路径长度。
实验目的
掌握图的邻接矩阵表示法;
掌握无向图的最小生成树算法(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;
}
}
}
作者自述
这篇整理可用了太多的时间,你们的鼓励是支持作者的无尽动力源泉!给作者一个小赞吧!