图论---最小生成树

树是一种特殊的图,具有很多特殊的性质。生成树问题研究的是将图中的所有顶点保留,但只选择图中的部分边,得到一棵树(也就是图的生成树)的问题。最小生成树则是在这些生成树中,边权之和最小的生成树。

可以使用prime算法或者kruskal算法求解最小生成树。

生成树相关概念

1、生成树定义
在一个V个点的无向连通图中,取其中V-1条边,并连接所有的顶点,所得到的子图称为原图的一棵生成树
2、树的属性
树是图的一种特殊形态。图G是树当且仅当以下任意一个条件成立
①G有V-1条边,无环;
②G有V-1条边,连通;
③任意两点之间只有唯一的简单路径
④G连通,但任意删除一条边后就不连通。
3、最小生成树
在一个带权的无向连通图中,各边权和最小的一棵生成树即为原图的最小生成树
4、最小边原则
图中权值最小的边(如果唯一的话)一定在最小生成树上
5、唯一性定理
对于一个图G,如果图中的边权值都不相同,则图的最小生成树是唯一的,反之不然。

Prime算法

prim

#include<iostream>
#include<cstring>
using namespace std;
const int INF=0X7ffffff/2;
int vst[505];//vst[i]标记顶点i是否加入最小生成树 
int d[505];//d[i]表示点i与当前生成树中的点有连边的边长最小值 
int g[505][505],n,m,ans=0;
void read()//读入数据,构建图 
{
	int i,j,x,y,w;
	cin>>n>>m;
	for(i=1;i<=n;i++)
	  for(j=1;j<=m;j++)
	     g[i][j]=INF;
    for(i=1;i<=m;i++)
	{
		cin>>x>>y>>w;
		g[x][y]=g[y][x]=w;
	 } 
}
void prim(int v0)
{
	int i,j,k,minn;
	memset(vst,0,sizeof(vst));//初始化生成树点集合 
	for(i=1;i<=n;i++) d[i]=INF;
	d[v0]=0;
	ans=0;
	for(i=1;i<=n;i++)//选择n个点 
	{
		minn=INF;
		for(j=1;j<=n;j++)//选择最小边 
		   if(vst[j]==0&&minn>d[j])
		     { minn=d[j];k=j; } 
        vst[k]=1;//标记 
        ans+=d[k]; 
        for(j=1;j<=n;j++)//修改d数组 
            if(vst[j]==0&&d[j]>g[k][j])
			   d[j]=g[k][j]; 
	}
}
int main()
{
	read();
	prim(1);
	cout<<ans<<endl;
	return 0;
}

kruskal算法

kruskal

#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=100005;
struct edge{int x,y,z;}a[maxn];
int n,m,prt[maxn],ans=0,bj;
bool cmp(edge x,edge y){return x.z<y.z;}
int getfather(int x)//查找祖先
{
	if(prt[x]==x) return x;
	prt[x]=getfather(prt[x]);
	return prt[x];
 } 
 void kruskal()
 {
 	int f1,f2,k,i;
 	k=0;
 	for(i=1;i<=n;i++) prt[i]=i;
 	for(i=1;i<=m;i++)
 	{
 		f1=getfather(a[i].x);
 		f2=getfather(a[i].y);
 		if(f1!=f2)
 		{
 			ans=ans+a[i].z;
 			prt[f1]=f2;
 			k++;
 			if(k==n-1) break; 
		 }
	 }
	 if(k<n-1){
	 	cout<<"impossible"<<endl;
	 	bj=0;
	 	return;
	 }
 }
 int main()
 {
 	cin>>n>>m;
	 ans=0;bj=1;
	 for(int i=1;i<=m;i++)
	  cin>>a[i].x>>a[i].y>>a[i].z;
	 sort(a+1,a+m+1,cmp); 
 }

相关练习

1、最小生成树
2、买礼物

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

信奥教练Andy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值