最小生成树两种方法实现

在数据结构中我们知道最小生成树有两种实现方法,这两种方法一定要熟练,其中prim方法开了两个辅助数组vis[]和dis[];kruskal方法采用了并查集并可以和优先队列(也可以直接用sort排序)结合起来,下面是个人两种方法在邻接表中的实现代码:

#include<iostream> 
#include<vector>
#include<queue> 
using namespace std;

const int maxv=1000;
const int maxe=1000;
const int inf=100000000; 
int n,e;// 结点数,边数 
struct node{
	int vex,weight;
};

vector<node>Adj[maxv];//定义邻接表 

//prim算法部分 
bool vis[maxv];//区别访问和未访问的集合
int dis[maxv];//更新各结点到集合最短距离 


int  prim() {//返回最小生成树之和 
for(int i=0;i<n;i++){ //初始化 
	vis[i]=false;
	dis[i]=inf;
} 
vis[0]=true; //v0点入集合
int k=0,min;//标记当前入集合结点
int sum=0;//记录最小路径和
for(int j=1;j<n;j++) { //剩余n-1个结点
	min=inf;
	for(int i=0;i<Adj[k].size();i++){ //更新dis 
	   int v=Adj[k][i].vex;
		if(Adj[k][i].weight<dis[v])
		dis[v]=Adj[k][i].weight;
	}
	for(int i=0;i<n;i++) {
		if(!vis[i]&&dis[i]<min)
		{
			k=i;
			min=dis[i];
		}
	}
	if(min==inf)return -1;//图不连通 
	sum+=min; 
	vis[k]=true;
}
return sum;
} 





//kruskal算法部分

int father[maxe];//并查集
struct edge{
	int x,y;//边两顶点
	int weight;//边权 
	edge(int a,int b,int c){
		x=a;
		y=b;
		weight=c;
	}
	edge(){
	}
}Edge[maxe]; 
 
struct cmp{
	bool operator ()( int a,int b){
		return Edge[a].weight>Edge[b].weight;	
	}
};
priority_queue<int,vector<int>,cmp>q;//优先队列存放最小边权下标


int  kruskal() {
	int sum=0;//记录最小路径和
	for(int i=0;i<e;i++)
	{father[i]=i;//并查集初始化 
	 q.push(i) ;//优先队列存放边 
	} 
    int temp=q.top();q.pop();  //先选出第一条边 
	sum+=Edge[temp].weight;
	int k=Edge[temp].x;   //标记该集合 
	father[Edge[temp].y] =k;
	for(int i=2;i<n;i++) {//选剩下n-2条边  
while(father[Edge[temp].x]==father[Edge[temp].y]&&!q.empty()) 
		{
			temp=q.top();q.pop(); //选出非闭环的边 
		}
		if(father[Edge[temp].x]==father[Edge[temp].y])//先不出边
		return -1; 
		sum+=Edge[temp].weight;
	  //标记该集合 
	father[Edge[temp].y] =father[Edge[temp].x]=k;
	//并入集合 ,路径压缩 		
	}
	return sum; 
} 

int main(){
	scanf("%d%d",&n,&e);
	int x,y,w;
	node temp;
	for(int i=0;i<e;i++) //初始化邻接表和边表 
	{
		scanf("%d%d%d",&x,&y,&w);
		temp.vex=y;temp.weight=w;
		Adj[x].push_back(temp);
		edge k(x,y,w);
		Edge[i]=k;
	}
	printf("%d\n",prim()) ;
	printf("%d\n",kruskal()) ;
	return 0;
}

这个部分应该多刷题以熟练应用,算是一个重点。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值