最小生成樹(1)——kruskal算法//SDNU1218

第一行國際慣例——咕咕咕。

本代碼以sdnu1218爲例

1.類似貪心的策略,先對邊按權值進行排序,不停的選擇最優邊進行構建樹
2.在構建過程中需要判斷是否有環(並查集判斷(如果不會並查集(我改天再補一下並查集博客
3.忽略我特別醜的代碼風格
4.可以增加優化(在kruskal函數的循環里加一個提前跳出的操作,當邊的個數>n-1時跳出即可(n爲點的個數(最小生成樹最多n-1條邊(此處略過
5.時間複雜度與邊的個數有關(適合稀疏圖
6.先寫kruskal是因爲我prim不會寫(這個晚上看了2/3時間的prim都不會寫(我果然菜的很在這裏插入圖片描述

#include <iostream>
#include <cstdio>
#include <algorithm>
#define inf 999999999999
#define maxn 200005
using namespace std;

int fa[maxn];
int n,m;
struct tree
{
    int u;
    int v;
    int cost;
} t[maxn];//用於存每條邊

void init()
{
    for(int i=0; i<maxn; ++i)
    {
        t[i].cost=inf;
        fa[i]=i;
    }
}//初始化所有的權值爲max,所有的父節點爲其本身

bool com(tree x,tree y)
{
    if(x.cost<y.cost)
        return true;
    else
        return false;
}//按權值從小到大排序

int tofind(int x)
{
    while(fa[x]!=x)
    {
        x=fa[x];
    }
    return x;
}//找到每個點的父節點

void tojoin(int x,int y)
{
    x=tofind(x);
    y=tofind(y);
    if(x!=y)
        fa[x]=y;
}//合併兩棵樹

int kruskal()
{
    int ans=0;
    for(int i=0; i<m; ++i)
    {
        int u=t[i].u;
        int v=t[i].v;
        if(tofind(u)==tofind(v))
            continue;//當兩個點的父節點爲同一節點(即早已聯通,下一個循環
        ans+=t[i].cost;
        tojoin(u,v);//合併兩個爲同一個棵樹
    }
    return ans;
}
int main()
{
    init();
    scanf("%d%d",&n,&m);
    for(int i=0; i<m; ++i)
    {
        int u,v,cost;
        scanf("%d%d%d",&t[i].u,&t[i].v,&t[i].cost);
    }//將每個邊儲存
    sort(t,t+m,com);//排序
    printf("%d\n",kruskal());
    return 0;
}

//後期應該會更新幾個練習題

發佈了41 篇原創文章 · 獲贊 10 · 訪問量 3495
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章