#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 克魯斯卡爾算法
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.