#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define MaxSize 100
typedef struct GraphEage
{
int front,rear,len;
struct GraphEage *next;
}GraphEage;
int Father[MaxSize];
void InsertSort(GraphEage *G,int a,int b,int len);
int Kruskal(GraphEage *G,int n,int m);
int Find(int child);
//查找最高父节点
int Find(int child)
{
if(Father[child] == child)return child;
else return Find(Father[child]);
}
//插入排序
void InsertSort(GraphEage *G,int a,int b,int len)
{
GraphEage *E,*R=G;
E = (GraphEage*)malloc(sizeof(GraphEage));
E->front = a;E->rear = b;E->len = len;
E->next = NULL;
//遍历插入
while (1)
{
if(R->next == NULL)
{ //链表中没有元素或者是遍历到最后时
R->next = E;
break;
}else if(len < R->next->len)
{ //下一个元素比他大 插入
E->next = R->next;
R->next = E;
break;
}
R = R->next;
}
}
/*克鲁斯卡尔算法*/
int Kruskal(GraphEage *G,int n,int m)
{ //ans记录最小生成树的边权之和
int ans = 0,i;
//并查集初始化,使父节点为自己本身
for(i = 0;i < n;i++)Father[i] = i;
//最小生成树的边数是 节点数-1
while(n > 1)
{
GraphEage *R = G->next;//获取集合中剩余边权最小的
G->next = G->next->next;//在集合中删除取出的这个元素
//寻找这条边两个节点的最高父节点
int a = Find(R->front);
int b = Find(R->rear);
if(a != b)//不相等说明不在一个集合中
{
Father[a] = b;//默认把 a 当作 b的父节点(可用秩优化)
ans += R->len;
n--;
}
}
return ans;
}
int main(int argc, char const *argv[])
{
GraphEage *G;
int n,m,i;
G = (GraphEage*)malloc(sizeof(GraphEage));
G->next = NULL;
printf("请输入节点数与边数:");
scanf("%d%d",&n,&m);
printf("请输入%d条边:\n",m);
for(i = 0;i < m;i++)
{
int a,b,len;
scanf("%d%d%d",&a,&b,&len);
InsertSort(G,a,b,len);
}
int ans = Kruskal(G,n,m);
printf("最小生成树的路径权值是:%d\n",ans);
return 0;
}
// 0 1 4
// 0 4 1
// 0 5 2
// 1 2 1
// 1 5 3
// 2 3 6
// 2 5 5
// 3 4 5
// 3 5 4
// 4 5 3
王道考研 ++++ Kruskal 克鲁斯卡尔算法
猜你喜欢
转载自blog.csdn.net/WX_1218639030/article/details/99414124
今日推荐
周排行