最小生成树-
1078 最小生成树
农民约翰被选为他们镇的镇长!他其中一个竞选承诺就是在镇上建立起互联网,并连接到所有的农场。当然,他需要你的帮助。 约翰已经给他的农场安排了一条高速的网络线路,他想把这条线路共享给其他农场。为了使花费最少,他想铺设最短的光纤去连接所有的农场。 你将得到一份各农场之间连接费用的列表,你必须找出能连接所有农场并所用光纤最短的方案。 每两个农场间的距离不会超过100000
第一行: 农场的个数,N(3<=N<=100)。
第二行..结尾: 接下来的行包含了一个N*N的矩阵,表示每个农场之间的距离。理论上,他们是N行,每行由N个用空格分隔的数组成,实际上,他们每行限制在80个字符以内,因此,某些行会紧接着另一些行。当然,对角线将会是0,因为线路从第i个农场到它本身的距离在本题中没有意义。
只有一个输出,是连接到每个农场的光纤的最小长度和。
4
0 4 9 21
4 0 8 17
9 8 0 16
21 17 16 0
28
使用prim算法,可在n^2内解决。其主要思想如下:
1.随意确定一个点,加入一个连通分量;
2.从这个连通分量向外扩展,不断加入离这个连通分量最近的点。
代码如下
#include<iostream>
#include<cstdio>
using namespace std;
int _(){ //读入优化
int a=getchar(),ans(0);
while(a<'0')a=getchar();
while(a>='0'&&a<='9') {
ans=ans*10+a-'0';
a=getchar();
}
return ans;
}
int ma[105][105],n,M=0x7fffffff;
int prim(){ //核心代码
int i,j,min,minb,mst[105]={},minc[105]={},sum(0);
for(i=2;i<=n;i++) minc[i]=ma[1][i],mst[i]=1; //将全部点的最近点确定为点1
mst[1]=0; //点1标记为已加
for(i=2;i<=n;i++){
min=M;
minb=0;
for(j=2;j<=n;j++)
if(minc[j]<min&&minc[j]) min=minc[j],minb=j; //更新最近点
sum+=min; //加入最近点的权值
minc[minb]=0; //最近点已加
for(j=2;j<=n;j++)
if(ma[minb][j]<minc[j])
minc[j]=ma[minb][j],mst[j]=minb; //更新离连通分量的权值
}
return sum;
}
int main(){
int i,j;
n=_();
for(i=1;i<=n;i++)
for(j=1;j<=n;j++) ma[i][j]=_();
cout<<prim()<<endl;
}

浙公网安备 33010602011771号