最小生成树
最小生成树有两种算法:
1、prim算法
2、kruskal算法
老师主要给我们讲了第二种算法。最小生成树是包含原图中的所有 n 个结点,并且有保持图连通的最少的边。也就是边权之和最小,并且可以联通所有点的无环图。
1、按边权进行排序
2、找出边权最小的边,如果它们不在一个集合(无环),那就加入最小生成树的集合中。
3、不符合条件就继续找。
4、直到找出n-1条边为止。
为什么要无环呢,因为形成环以后,即使不用这条边,整个图也是能够联通的,所以说这条边是不必要的。排在前面把整个图联通起来的边必定是最短的,是最优的选择。
但是要注意,在合并最小生成树时,是把它们的祖先合并,并不是两个数合并。这可是个大错误!!!
参考代码——
struct ee{
int to;
int from;
int l;
}f[10005];
bool cmp(ee x,ee y)
{
return x.l<y.l;
}//排序
int finda(int x)
{
if(father[x]==x) return x;
return father[x]=finda(father[x]);
}
int main()
{
freopen("1592.in","r",stdin);
freopen("1592.out","w",stdout);
cin>>n;
for(int i=1;i<=n;i++) father[i]=i;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
cin>>a;
if(a==0) continue;
else
{
e++;
f[e].from=i;
f[e].to=j;
f[e].l=a;
}
}
}
sort(f+1,f+1+e,cmp);
int ans=0;
for(int i=1;i<=e;i++)
{
if(finda(f[i].from)!=finda(f[i].to))//判断是否在同一个并查集里
{
ans+=f[i].l;
father[finda(f[i].from)]=finda(f[i].to);//合并祖先
}
}
cout<<ans<<endl;
return 0;
}

浙公网安备 33010602011771号