城市联网 村修路 最小成本问题————Prim算法

最小生成树问题————Prim算法

实现一个程序用最小成本将若干个城市进行联网
要求
给出将两个城市进行联通的成本。要求使用最小成本将所有城市进行联网
输入
N(表示城市数目)
接下来是若干组三元组(a,b,x)表示a城市到b城市联通的成本为x,以-1为结尾
输出
给出N-1个二元组(a,b)表示联网时需要将a和b连接起来

最小生成树问题,采用Prim算法,在图上任取一点为一根树。
把该点加入终点集遍历图中所有与树相连的边,取其中权值最小的边,把该边加入边集,与之对应的不在终点集中的点加入终点集。
递归上述操作让一个小树长大,当边集中的元素为N-1时结束。

#include "iostream"
using namespace std;
int a[1000][3];//三元组 
int b[100];//终点集 
int c[200];//边集
int count;//三元组数量 
int n;//城市数量 
int main()
{
	void prim(int m); 	
	int i;
	 
	cin>>n;
	for(i=0;i<1000;i++)
	{
		cin>>a[i][0];
		if(a[i][0]==-1)	//输入结束 
		break;
		cin>>a[i][1];
		cin>>a[i][2];
	}
	count=i;
	b[0]=a[0][0];//初始化,任一点放入边集 
	prim(0);//实参为 边集内已有边数 


	for(i=0;i<2*(n-1);i=i+2)
	{
		cout<<c[i]<<" "<<c[i+1]<<endl;
	}
	return 0;
}
void prim(int m)  
{
	
	if(m==n)	//边集内有n-1条边结束 
	{
		return;
	}
	/*cout<<"终点集:";
	for(int i=0;i<=m;i++)
	{
		cout<<b[i];
	}
	cout<<endl;*/ 
	int k=0,min=10000,dj=0,ej=0,fj=0;
	
	for(int i=0;i<=m;i++)	 
	{
		for(int j=0;j<count;j++)	//二重循环,寻找与最小生成树相连的边 
		{
			if(b[i]==a[j][0])
			{
				for(int cj=0;cj<=m;cj++)	//对于边的两点都再终点集内的边过滤 
				{
					if(a[j][1]==b[cj])
					{
						a[j][0]=0;
						a[j][1]=0;
						dj=1;
						break;
					}
				}
				if(dj==1)
				{
					dj=0;
					continue;
				}
				if(a[j][2]<min)				//不断选择权值最小的边 并记录此边在三元组中的位置 
				{
					//cout<<"入集:"<<j<<" "<<a[j][2]<<endl;
					ej=j;
					fj=1;
					min=a[j][2];
				}
			}
			if(b[i]==a[j][1])
			{
				for(int cj=0;cj<=m;cj++)
				{
					if(a[j][0]==b[cj])
					{
						a[j][0]=0;
						a[j][1]=0;
						dj=1;
						break;
					}
				}
				if(dj==1)
				{
					dj=0;
					continue;
				}
				if(a[j][2]<min)
				{
					ej=j;
					fj=0;
					min=a[j][2];
				}
			}
		 } 
	 }
	 b[m+1]=a[ej][fj];				//点、边收入终点集 边集 该三元组置0 
	 c[2*m]=a[ej][0];
	 c[2*m+1]=a[ej][1];
	 a[ej][0]=0;
	 a[ej][1]=0;
	prim(m+1);						//m的值加一; 
 } 
  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值