最小生成树(克鲁斯卡尔算法)PTA 6-27

先讲思路,答案第一段代码,题目在最后;

思路:这里的图时矩阵实现,所以要把矩阵遍历一遍并且把边提取出来初始化为Edge边集;并且为了判断是否成环,要设立一个集合S(并查集),初始化后的边集还要根据lowcost排升序,这样在接下来选取边的时候可以直接顺序取并判断; 完成以上后,进入循环for(i=0;i<ie;i++)来遍历边集Edge的每条边(v,w);找下标调用了裁判程序给定的LocateVex函数(根据值确定其在G中下标的函数),if(Find(S,v)!=Find(S,w))说明(v,w)不在同一棵树上,不会成环,就把v和w连接(连接即让它们祖先一样,S[w]=S[v]),并且给代表最小生成树边数的MstS加一,如果满足MstS==G.vexnum-1,则说明边已经收集满了,跳出循环;

和书上有点差别。先排序再生成;书上是一边生成一边堆排序找最小;

答案代码如下:

int Find(int S[],int a){
    int i;
	for(i=a;S[i]!=i;i=S[i]);
	S[a]=i;//顺便路径压缩以下 
	return i;
}
void Kruskal(AMGraph G){
	static int S[9999],i,j,ie,v,w,MstS=0;
	for(i=0;i<G.vexnum;i++){//初始化集合 
		S[i]=i;
	}
	for(i=0;i<G.vexnum;i++){//初始化边结构体 
		for(j=0;j<G.vexnum;j++){
			if(G.arcs[i][j]<MaxInt&&j>i){//根据输出要求,每条边先输出下标大的 
				Edge[ie].Head=G.vexs[i];
				Edge[ie].Tail=G.vexs[j];
				Edge[ie++].lowcost=G.arcs[i][j];//记录边长,同时ie++ 
			}
		}
	}
	//对边结构体排升序  冒泡 
	for(i=0;i<ie;i++){
		for(j=0;j<ie-i-1;j++){
			if(Edge[j+1].lowcost<Edge[j].lowcost){
				struct Evode t=Edge[j];
				Edge[j]=Edge[j+1];
				Edge[j+1]=t; 
			}
		}
	}
	for(i=0;i<ie;i++){//走完原图的边集  i就是每次的最小边在Edge里的下标 
		v=LocateVex(G,Edge[i].Head);//找到这条边的起点 
		w=LocateVex(G,Edge[i].Tail);
//        printf("%d %d %d %d\n",v,w,Find(S,v),Find(S,w));
		if(Find(S,v)!=Find(S,w)){//说明不会成换环 
			S[w]=S[v];//S[v]=S[w]
			MstS++;//收集的边数加一
			printf("%c->%c\n",Edge[i].Head,Edge[i].Tail);//输出已经确定的边 
			if(MstS==G.vexnum-1) break;//已经收集够边数了  结束 
		} 
		//else 丢弃这条边,就什么也不做 
	}
}

题目如下:

试实现克鲁斯卡尔最小生成树算法。

函数接口定义:

 

void Kruskal(AMGraph G);

其中 G 是基于邻接矩阵存储表示的无向图。

裁判测试程序样例:

#include <stdio.h>
#define MVNum 10 
#define MaxInt 32767 

typedef struct{ 
    char vexs[MVNum];
    int arcs[MVNum][MVNum];
    int vexnum,arcnum; 
}AMGraph;

struct Evode{
    char Head;
    char Tail;
    int lowcost;
}Edge[(MVNum * (MVNum - 1)) / 2];

int Vexset[MVNum];
void CreateUDN(AMGraph &G);//实现细节隐藏
void Kruskal(AMGraph G);
int main(){
    AMGraph G;
    CreateUDN(G);
    Kruskal(G);
    return 0;
}
/* 请在这里填写答案 */

输入样例:

第1行输入结点数vexnum和边数arcnum。第2行输入vexnum个字符表示结点的值,接下来依次输入arcnum行,每行输入3个值,前两个字符表示结点,后一个数表示两个结点之间边的权值。

7 9
0123456
0 1 28
0 5 10
1 2 16
1 6 14
2 3 12
3 6 18
3 4 22
4 5 25
4 6 24

输出样例:

按最小生成树的生成顺序输出每条边。

0->5
2->3
1->6
1->2
3->4
4->5 

ww.png

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值