求图的最小生成树的prime算法和Kruskal算法

prime算法原理

1.首先清空树,任取一个顶点加入生成树。

2.在那些一个顶点在生成树李,另一个顶点不在生成树里德边中,选取边权最小的一条边,把这条边的另一个顶点加入生成树。

3.重复步骤2,直到所有的顶点均加入了生成树。

如图所示:


代码:

int map[max][max];
int vis[max];
int d[max];
int prime()
{
	int sum=0;
	int index=1; //先将顶点1加入生成树
	vis[1]=1;    //标记顶点1
    for(int i=0;i<m;i++)  //将与顶点1相连的边的权值赋给d数组
    {
    	d[i]=map[index][i];
    }
    for(int i=1;i<m;i++)
    {
    	int min=MAX;  //MAX为定义的无穷大
    	for(int j=0;j<m;j++) //找边权最小值
    	{
    		if(!vis[j] && d[j]<min)
    		{
    			min=d[j];
    			index=j;
    		}
    	}
    	vis[index]=1;//标记掉(把index加入生成树)
    	sum+=min;
    	for(int j=0;j<m;j++)//更新边权
    	{
          if(!vis[j] && d[j]>map[index][j])
          	d[j]=map[index][j];
    	}
    }
    return sum;
}
int main()
{
/*要在主函数中先将map数组定义为无穷大,
	将vis数组清空,然后在输入顶点与边权*/
	for(int i=0;i<max;i++)
	{
		for(int j=0;j<max;j++)
		{
			map[i][j]=MAX;
		}
	}
	memset(vis,0,sizeof(vis));
}

Kruskal算法

原理:先将子图看成一个只含有n个顶点的不含边的图,各个顶点看成是各自树的根节点。

从边集中选取一条权值最小的边,判断该边的两个顶点是否分属不同的树,若是则将其加入子图,然后将这两个顶点分别所在的树合成一棵树;若不是,则说明这两个点已在一颗树上,不可取。(用到了并查集)

代码:

int father[max];
int rank[max];
struct node
{
	//将边的边权、起点、终点
	int val,start,end;
}edge[边的最多的条数];

void make()//初始化
{
	for(int i=0;i<n;i++)
	{
		father[i]=i;
		rank[i]=1;
	}
}

int find(int x)//找根节点
{
	int i,j=x;
	while(j!=father[j])
	{
		j=father[j];
	}
	while(x!=j)
	{
		i=father[x];
		father[x]=j;
		x=i;
	}
	return j;
}

void union(int x,int y)
{
	x=find(x);
	y=find(y);
	if(x==y)
		return;
	if(rank[x]<rank[y])//合并
	{
		father[x]=find(y);
	}
	else
	{
		if(rank[x]==rank[y])
		{
			rank[x]++;
		}
		father[y]=find(x);
	}

}
int Kruskal(int n)
{
	int sum=0;
	make();
	for(int i=0;i<n;i++)//从边权最小的边开始加入图中
	{
		if(find(edge[i].start)!=find(edge[i].end))
		{
			union(edge[i].start,edge[i].end);
			sum+=edge[i].val;
		}
	}
	return sum;
}
bool cmp(node a,node b)
{
	return a.val<b.val;
}
int main()
{
	//输入边的边权,起点,终点
	//在主函数内将边按边权从小到大排序
	sort(edge,edge+边的条数,cmp);
	int ans=Kruskal(n);//n为边的数量
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值