Prim算法另一种形式

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
#define MAXN 10000
#define MAXM 1000
#define INF 0X7FFFFFFF
struct node{//1 原图 2 生成树  生成树要存起来
	int to;
	int weight;
	int next;
}edge1[MAXM],edge2[MAXM];
int head1[MAXN],head2[MAXN];
int cnt1,cnt2;
int n,m;
void Init(){
	cnt1=0;
	cnt2=0;
	memset(edge1,0,sizeof(edge1));
	memset(head1,0,sizeof(head1));
	memset(edge2,0,sizeof(edge2));
	memset(head2,0,sizeof(head2));
}
void Add(int x,int y,int z,int num){
	if(num==1){
		cnt1++;
		edge1[cnt1].to=y;
		edge1[cnt1].weight=z;
		edge1[cnt1].next=head1[x];
		head1[x]=cnt1;
	}
	else{
		cnt2++;
		edge2[cnt2].to=y;
		edge2[cnt2].weight=z;
		edge2[cnt2].next=head2[x];
		head2[x]=cnt2;
	}
}
void Prim(){
	int i,j,t;
	int Min,minIndex,sum=0;
	int *dis=new int[n];//当前生成树内的点 到树外其他点的最短距离
	int *parent=new int[n];//生成树中每个节点的父节点
	for(int i=1;i<=n;i++){
		dis[i]=INF;
	}
	dis[1]=0;//把1节点加入树中 加入树中的,dis均为0
	parent[1]=0;
	for(i=1;i<=n;i++){
        Min=INF;
		for(j=1;j<=n;j++){
			if(dis[j]!=-1&&dis[j]<Min){
				Min=dis[j];
				minIndex=j;
			}
		}
		if(Min==INF){//没有最小生成树
			cout<<"ERROR"<<endl;
			return;
		}
		sum+=dis[minIndex];
		Add(parent[minIndex],minIndex,dis[minIndex],2);
		dis[minIndex]=-1;
		for(t=head1[minIndex];t;t=edge1[t].next){
			if(dis[edge1[t].to]>edge1[t].weight){
				dis[edge1[t].to]=edge1[t].weight;
				parent[edge1[t].to]=minIndex;
			}
		}
	}
	cout<<sum<<endl;
	delete dis;
}
int main(){
	int x,y,z;
	cin>>n>>m;
	for(int i=1;i<=m;i++){
		cin>>x>>y>>z;
		Add(x,y,z,1);
		Add(y,x,z,1);
	}
	Prim();
	return 0;
}

可以看出,此算法与单源最短路Dijkstra算法很像,此代码也可以进行堆优化:

#include <cstdio>
#include <cstring>
#include <queue>
#include <iostream>
using namespace std;
#define INF 0X7FFFFFFF
int n,m,cnt,head[1005];
struct node{
	int to;
	int weight;
	int next;
}edge[10000];
struct node1{
	int to,cost;
	node1(int x,int y):to(x),cost(y){}
	bool operator<(node1 a)const{
		return this->cost>a.cost;
	}
};
void Add(int x,int y,int w){
	cnt++;
	edge[cnt].to=y;
	edge[cnt].weight=w;
	edge[cnt].next=head[x];
	head[x]=cnt;
}
void Prim(){//设点从1到N
	int sum=0,dis[n+1],book[n+1];
	priority_queue<node1> q;
	for(int i=1;i<=n;i++){
		dis[i]=INF;
	}
	dis[1]=0;
	memset(book,0,sizeof(book));
	q.push(node1(1,0));
	while(!q.empty()){
		node1 t=q.top();
		q.pop();
		if(book[t.to]){
			continue;
		}
		sum+=t.cost;//由此可以看出,不加book标记不可以
		book[t.to]=1;
		for(int i=head[t.to];i;i=edge[i].next){
			if(edge[i].weight<dis[edge[i].to]){
				dis[edge[i].to]=edge[i].weight;
				q.push(node1(edge[i].to,edge[i].weight));
			}
		}
	}
	cout<<sum<<endl;
}
int main(){
	int x,y,w;
	cin>>n>>m;
	for(int i=1;i<=m;i++){
		cin>>x>>y>>w;
		Add(x,y,w);
		Add(y,x,w);
	}
	Prim();
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值