如何构造可以使N个城市连接的最小生成树

rainingskyzlf 2007-01-17 03:51:23
问题描述:
给顶一个地区的N个城市间的距离网,用PRIM算法或KRUSKAL算法建立最小生成树,并计算得到的最小生成树的代价.
基本要求:
1.城市间的距离采用邻接矩阵表示,邻接矩阵的存储结构定义采用课本中给出的定义,若两个城市之间不存在道路,则将相应边的权值设为自己定义的无穷大值.要求在屏幕上显示得到的最小生成树作用包括了哪些城市间的道路,并显示得到的最小生成树的代价.
2.表示城市间距离网的临界矩阵(要求最小6个城市,10条边).
3.最小生成树中宝库的边及其权值,并显示得到的最小生成树的代价.
...全文
2449 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
mad_liu 2012-05-28
  • 打赏
  • 举报
回复
我的课程设计终于有找落了
jixingzhong 2007-01-17
  • 打赏
  • 举报
回复
最小生成树 原理、构造方法:

http://www.chinaitlab.com/www/techspecial/soft/tu-zuixiaoshengchengshu.htm
jixingzhong 2007-01-17
  • 打赏
  • 举报
回复
算法过程如上所述,
代码可以参考如下:
/*Prim 普里姆算法*/
#include "stdio.h"
#define n 6
typedef struct
{
int fromvex,endvex;
float length;
}edge;

edge T[n-1];

float dist[n][n]={{100000,10,100000,100000,19,21},
{10,100000,5,6,100000,11},
{100000,5,100000,6,100000,100000},
{100000,6,6,100000,18,14},
{19,100000,100000,18,100000,33},
{21,11,100000,14,33,100000}};

void Prim(int i)
{
int j,k,m,v;
float min,max=100000;
float d;
edge e;
v=i;
for(j=0;j<=n-2;j++)
{
T[j].fromvex=v;
if(j>=v)
{
T[j].endvex=j+1;
T[j].length=dist[v][j+1];
}
else
{
T[j].endvex=j;
T[j].length=dist[v][j];
}
}
for(k=0;k<n-1;k++)
{
min=max;
for(j=k;j<n-1;j++)
if(T[j].length<min)
{
min=T[j].length;
m=j;
}
e=T[m];
T[m]=T[k];
T[k]=e;
v=T[k].endvex;
for(j=k+1;j<n-1;j++)
{
d=dist[v][T[j].endvex];
if(d<T[j].length)
{
T[j].length=d;
T[j].fromvex=v;
}
}
}
}

int main()
{
int i;
Prim(2);
for(i=0;i<n-1;i++)
{
printf("%d--%.0f-->%d\n",T[i].fromvex,T[i].length,T[i].endvex);
}
return 0;
}
jixingzhong 2007-01-17
  • 打赏
  • 举报
回复
假设要在n个城市之间建立通讯联络网,则连通n个城市只需n-1条线路。如何在最节省经费的前提下,建立这个通讯网。n个城市的初始连通图具有n*(n-1)/2条边,每条边都有权值。如何造出这个具有最小代价的只有n-1条线路的n个城市通讯网呢?

分析:
普里姆算法是先连接n个顶点中“权值”最小的一条边,再连接和这两个顶点相连的“权值” 最小的一条边,依次下去,直到n个顶点连成了n-1条边为止。这是一个“边、边相接”的过程。

克鲁斯卡尔算法是先连接n个顶点中“权值”最小的一条边,再在所剩顶点中连接和这两个顶点不相连的“权值”最小的一条边,当没有(n为偶数)或只有一个(n为奇数)孤立点存在时,再将所剩边中权值最小的边连接起来,直到n个顶点连成了n-1条边为止。这是一个“边、边先分后合为一体”的过程。
chenhu_doc 2007-01-17
  • 打赏
  • 举报
回复
//cpp文件


#include "MSTree.h"
#include <iostream.h>
#include <stdlib.h>
#include <iomanip.h>

void main()
{
int i;
adjmatrix GA;
edge *CT;//指向边的指针
edge *C;
edge *GE;
int e,n,ch;
cout<<"***** WELCOME *****"<<endl;
cout<<"请输入顶点数n,边数e:(用空格隔开)"<<endl;
cin>>n>>e;
cout<<"你打算采用那种算法?"<<endl;
cout<<"1. Kruskal 算法"<<endl;
cout<<"2. Prim 算法"<<endl;
cout<<"请输入你的选择(1 or 2):";
cin>>ch;
switch(ch)
{
case 1:
GE=CreateES(n,e);
GE=SortGE(GE,e);
cout<<"经过排序后:"<<endl;
cout<<"----------"; //从这里开始绘制表格;
for(i=0;i<e;i++)
cout<<"----";
cout<<endl;
cout<<"fromvex: |";
for(i=0;i<e;i++)
cout<<setw(3)<<GE[i].fromvex<<'|';
cout<<endl;
cout<<"endvex : |";
for(i=0;i<e;i++)
cout<<setw(3)<<GE[i].endvex<<'|';
cout<<endl;
cout<<"weight : |";
for(i=0;i<e;i++)
cout<<setw(3)<<GE[i].weight<<'|';
cout<<endl;
cout<<"----------"; //到这里绘制表格结束;
for(i=0;i<e;i++)
cout<<"----";
cout<<endl;
C=Kruskal(GE,n,e);
cout<<"Kruskal算法求得的最小生成树为:"<<endl;
for(i=0;i<n-1;i++)
cout<<'<'<<C[i].fromvex<<','<<C[i].endvex<<'>'<<C[i].weight<<' ';
cout<<endl<<"处理结束,再见!"<<endl;
break;
case 2:
CreateAM(GA,n,e);
CT=Prim(GA,n);
cout<<"Prim算法求得的最小生成树为:"<<endl;
for(i=0;i<n-1;i++)
cout<<'<'<<CT[i].fromvex<<','<<CT[i].endvex<<'>'<<CT[i].weight<<' ';
cout<<endl<<"处理结束,再见!"<<endl;
break;
default:cout<<"输入有误!"<<endl;
}
}


//.h文件

#include <stdio.h>
#include <iostream.h>
#include <stdlib.h>

const int MaxVertexNum=30;
const int MaxValue=50; //最大权值
typedef int VertexType; //顶点信息类型为整型
typedef VertexType vexlist[MaxVertexNum];
typedef int adjmatrix[MaxVertexNum][MaxVertexNum];//邻接矩阵
struct edge{ //边结构
int fromvex; //起点
int endvex; //终点
int weight;//权值
};
struct edgenode{//边结点
int adjvex;
edgenode *next;//指向边结点的指针
};
void CreateAM(adjmatrix &GA,int n,int e) //里姆算法构造无向图
{
vexlist GV;
int i,j,k,w;
cout<<"输入"<<n<<"个顶点:(之间用空格隔开)"<<endl;
for(i=0;i<n;i++)
cin>>GV[i];//输入顶点的个数
for(i=0;i<n;i++)
for(j=0;j<n;j++){
if(i==j) GA[i][j]=0;
else
GA[i][j]=MaxValue;//把权值初始化为最大权值
}
cout<<"输入"<<e<<"条边:(格式:fromvex endvex weight)"<<endl;
for(k=0;k<e;k++){ //输入边
cout<<"输入第"<<k+1<<"条边:";
cin>>i>>j>>w;
GA[i][j]=GA[j][i]=w;//此图为无向图,对称权值相等
}
}

edge *CreateES(int n,int e) //为克鲁斯卡尔算法构造无向图
{
int i,j,k,w;
vexlist GV;
cout<<"输入"<<n<<"个顶点:(之间用空格隔开)"<<endl;
for(i=0;i<n;i++)
cin>>GV[i];
cout<<"输入"<<e<<"条边:(格式:fromvex endvex weight)"<<endl;
edge *GE=(edge *)malloc(e*sizeof(edge));
for(k=0;k<e;k++){
cout<<"输入第"<<k+1<<"条边:";
cin>>i>>j>>w;
GE[k].fromvex=i;
GE[k].endvex=j;
GE[k].weight=w;
}
return GE;
}

edge *SortGE(edge *GE,int e)//按权值的大小排序
{
int i,j,flag;
edge temp;
for(i=0;i<e;i++)
{
flag=0;
for(j=e-1;j>=i;j--)
if(GE[j-1].weight>GE[j].weight){
temp=GE[j-1];
GE[j-1]=GE[j];
GE[j]=temp;
flag=1;
}
if(flag==0)
return GE;
}
}

edge *Kruskal(edge *GE,int n,int e)//用克鲁斯尔算法求最小生成树
{
int i,j;
adjmatrix s;
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
if(i==j) s[i][j]=1;
else
s[i][j]=0;
}
int k(1),d(0),m1,m2;
edge *C=new edge[n-1];
for(i=0;i<n-1;i++)
C[i].fromvex=C[i].endvex=C[i].weight=0;
while(k<n)
{
for(i=0;i<n;i++)
{
for(j=0;j<n;j++){
if(GE[d].fromvex==j&&s[i][j]==1) m1=i;
if(GE[d].endvex==j&&s[i][j]==1) m2=i;
}
}
if(m1!=m2)
{
C[k-1]=GE[d];
k++;
for(j=0;j<n;j++)
{
s[m1][j]=s[m1][j]||s[m2][j];
s[m2][j]=0;
}
}
d++;
}
return C;
}

edge *Prim(adjmatrix GA,int n)//用普里姆算法求最小生成树
{
int i,j,k,min,t,m,w;
edge *CT=new edge[n-1];
for(i=0;i<n-1;i++)
{
CT[i].fromvex=0;
CT[i].endvex=i+1;
CT[i].weight=GA[0][i+1];
}
for(k=1;k<n;k++)
{
min=MaxValue;
m=k-1;
for(j=k-1;j<n-1;j++)
if(CT[j].weight<min){
min=CT[j].weight;
m=j;
}
edge temp=CT[k-1];
CT[k-1]=CT[m];
CT[m]=temp;
j=CT[k-1].endvex;
for(i=k;i<n-1;i++)
{
t=CT[i].endvex;
w=GA[j][t];
if(w<CT[i].weight){
CT[i].weight=w;
CT[i].fromvex=j;
}
}
}
return CT;
}
rainingskyzlf 2007-01-17
  • 打赏
  • 举报
回复
急...请各位大虾帮下忙额!!

64,685

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧