最优布线问题&普里姆算法【最小生成树】

探讨如何使用普里姆算法解决最优布线问题,实现计算机网络的最小成本连接,详细解析算法流程与实现代码。

最优布线问题&普里姆算法

Time Limit:10000MS Memory Limit:65536K
Total Submit:274 Accepted:178
Case Time Limit:1000MS


Description
学校有n台计算机,为了方便数据传输,现要将它们用数据线连接起来。两台计算机被连接是指它们之间有数据线连接。由于计算机所处的位置不同,因此不同的两台计算机的连接费用往往是不同的。
当然,如果将任意两台计算机都用数据线连接,费用将是相当庞大的。为了节省费用,我们采用数据的间接传输手段,即一台计算机可以间接的通过若干台计算机(作为中转)来实现与另一台计算机的连接。
现在由你负责连接这些计算机,你的任务是使任意两台计算机都连通(不管是直接的或间接的)。


Input
输入文件wire.inwire.inwire.in,第一行为整数 nnn(2<=n<=100)(2<=n<=100)2<=n<=100,表示计算机的数目。此后的nnn行,每行nnn个整数。第x+1x+1x+1yyy列的整数表示直接连接第xxx台计算机和第yyy台计算机的费用。

Output
输出文件wire.outwire.outwire.out,一个整数,表示最小的连接费用。


Sample Input
3
0 1 2
1 0 1
2 1 0

Sample Output
2(注:表示连接1和2,2和3,费用为2)


Hint
FillcharFillcharFillchar(f,sizeof(f),(f,sizeof(f),(f,sizeof(f),$7f)7f)7f) 把所有值赋值为最大


解题思路

算法分析&思想讲解: PrimPrimPrim算法每次循环都将一个蓝点uuu变为白点,并且此蓝点uuu与白点相连的最小边权min[u]min[u]min[u]还是当前所有蓝点中最小的。这样相当于向生成树中添加n−1n-1n1次最小的边,最后得到的一定是最小生成树。
在这里插入图片描述
初始时所有点都是蓝点,min[1]=0,min[2、3、4、5]=min[1]=0,min[2、3、4、5]=min[1]=0min[2345]=无穷大。权值之和=0=0=0
在这里插入图片描述
第一次循环自然是找到min[1]=0最小的蓝点1。将1变为白点,接着枚举与1相连的所有蓝点2、3、4,修改它们与白点相连的最小边权。
min[2]=a[1][2]=2;min[2]=a[1][2]=2;min[2]=a[1][2]=2 min[3]=a[1][3]=4;min[3]=a[1][3]=4;min[3]=a[1][3]=4 min[4]=a[1][4]=7;min[4]=a[1][4]=7;min[4]=a[1][4]=7 min[5]=∞;min[5]=∞;min[5]=
在这里插入图片描述
第二次循环是找到min[2]最小的蓝点2。将2变为白点,接着枚举与2相连的所有蓝点3、5,修改它们与白点相连的最小边权。
min[3]=a[2][3]=1;min[3]=a[2][3]=1;min[3]=a[2][3]=1 min[5]=a[2][5]=2;min[5]=a[2][5]=2;min[5]=a[2][5]=2
在这里插入图片描述
第三次循环是找到min[3]最小的蓝点3。将3变为白点,接着枚举与3相连的所有蓝点4、5,修改它们与白点相连的最小边权。
min[4]=w[3][4]=1;min[4]=w[3][4]=1;min[4]=w[3][4]=1
由于min[5]=2<w[3][5]=6;min[5]=2 < w[3][5]=6;min[5]=2<w[3][5]=6所以不修改min[5]min[5]min[5]的值。
注意:这里是指一个蓝点到白点集合的最短距离,不是道一个白点的距离。
例:3到白点集合的最短距离为1。


代码

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
int n,a[200][200],minn[200],v[200],ans,k;//minn存放蓝点i到白点的最短距离,v标记i是否已经加入最小生成树
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		cin>>a[i][j];
	}
	memset(minn,0X7f,sizeof(minn));//初始设为无穷大
	minn[1]=0;
	for(int i=1;i<=n;i++)//要连n个点
	{
		k=0;
		for(int j=1;j<=n;j++)//找一个与白点相连的权值最小的蓝点k
		{
		   if(!v[j]&&minn[j]<minn[k])
	     	  k=j;
		}
		v[k]=1;
		for(int j=1;j<=n;j++)//修改与k相连的所有蓝点
		{
			if(a[k][j]<minn[j]&&!v[j])
			minn[j]=a[k][j];
		}
	}
	for(int i=1;i<=n;i++)
	ans+=minn[i];
	cout<<ans;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值