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

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

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


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


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

Output
输出文件 w i r e . o u t wire.out wire.out,一个整数,表示最小的连接费用。


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

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


Hint
F i l l c h a r Fillchar Fillchar ( f , s i z e o f ( f ) , (f,sizeof(f), (f,sizeof(f),$ 7 f ) 7f) 7f) 把所有值赋值为最大


解题思路

算法分析&思想讲解: P r i m Prim Prim算法每次循环都将一个蓝点 u u u变为白点,并且此蓝点 u u u与白点相连的最小边权 m i n [ u ] min[u] min[u]还是当前所有蓝点中最小的。这样相当于向生成树中添加 n − 1 n-1 n1次最小的边,最后得到的一定是最小生成树。
在这里插入图片描述
初始时所有点都是蓝点, m i n [ 1 ] = 0 , m i n [ 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,修改它们与白点相连的最小边权。
m i n [ 2 ] = a [ 1 ] [ 2 ] = 2 ; min[2]=a[1][2]=2; min[2]=a[1][2]=2 m i n [ 3 ] = a [ 1 ] [ 3 ] = 4 ; min[3]=a[1][3]=4; min[3]=a[1][3]=4 m i n [ 4 ] = a [ 1 ] [ 4 ] = 7 ; min[4]=a[1][4]=7; min[4]=a[1][4]=7 m i n [ 5 ] = ∞ ; min[5]=∞; min[5]=
在这里插入图片描述
第二次循环是找到min[2]最小的蓝点2。将2变为白点,接着枚举与2相连的所有蓝点3、5,修改它们与白点相连的最小边权。
m i n [ 3 ] = a [ 2 ] [ 3 ] = 1 ; min[3]=a[2][3]=1; min[3]=a[2][3]=1 m i n [ 5 ] = a [ 2 ] [ 5 ] = 2 ; min[5]=a[2][5]=2; min[5]=a[2][5]=2
在这里插入图片描述
第三次循环是找到min[3]最小的蓝点3。将3变为白点,接着枚举与3相连的所有蓝点4、5,修改它们与白点相连的最小边权。
m i n [ 4 ] = w [ 3 ] [ 4 ] = 1 ; min[4]=w[3][4]=1; min[4]=w[3][4]=1
由于 m i n [ 5 ] = 2 < w [ 3 ] [ 5 ] = 6 ; min[5]=2 < w[3][5]=6; min[5]=2<w[3][5]=6所以不修改 m i n [ 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;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值