最小生成树

最小生成树有两种算法:

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;
}

  

posted @ 2017-08-19 16:31  yiyiyizqy  阅读(124)  评论(0编辑  收藏  举报