最优布线问题&普里姆算法
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+1行yyy列的整数表示直接连接第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-1n−1次最小的边,最后得到的一定是最小生成树。

初始时所有点都是蓝点,min[1]=0,min[2、3、4、5]=min[1]=0,min[2、3、4、5]=min[1]=0,min[2、3、4、5]=无穷大。权值之和=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;
}
探讨如何使用普里姆算法解决最优布线问题,实现计算机网络的最小成本连接,详细解析算法流程与实现代码。
143

被折叠的 条评论
为什么被折叠?



