c++最小生成樹之克魯斯卡爾

最小生成樹有兩個算法,一個是prim,一個是kruskarl。prim算法就相當于以點為主,來找最小生成樹
而kruskarl算法就是著眼于邊了

核心思想

1.將所有邊按從小到大排序
2.枚舉某一條邊,若與邊相連的兩個點不在同一個集合,就合并這兩個點,不然就跳過(此處會用到并查集),不會并查集的話可以看看我以前寫的并查集
3.(重點)若邊數(shù)=點數(shù)-1,則最小樹成功生成。原理:這其實就是數(shù)學,一條邊有兩條端點,兩條邊因為共用一個端點,所以是三個端點(如下)

.___.___.

這就是三個點時邊的情況

實現(xiàn)

原題
文字稿如下

題目描述

如題,給出一個無向圖,求出最小生成樹,如果該圖不連通,則輸出orz

輸入輸出格式

輸入格式:
第一行包含兩個整數(shù)N、M,表示該圖共有N個結點和M條無向邊。(N<=5000,M<=200000)

接下來M行每行包含三個整數(shù)Xi、Yi、Zi,表示有一條長度為Zi的無向邊連接結點Xi、Yi

輸出格式:
輸出包含一個數(shù),即最小生成樹的各邊的長度之和;如果該圖不連通則輸出orz

輸入輸出樣例

輸入樣例#1: 復制
4 5
1 2 2
1 3 2
1 4 3
2 3 4
3 4 3
輸出樣例#1: 復制
7
說明

時空限制:1000ms,128M

數(shù)據(jù)規(guī)模:

對于20%的數(shù)據(jù):N<=5,M<=20

對于40%的數(shù)據(jù):N<=50,M<=2500

對于70%的數(shù)據(jù):N<=500,M<=10000

對于100%的數(shù)據(jù):N<=5000,M<=200000

我用了一個結構體來存儲(也可以用鏈式前向星)

const int M=200100;
struct node{
    int x;//出發(fā)節(jié)點
    int y;//到達節(jié)點
    int w;//邊長度
}a[M];

讀入

cin>>n>>e;
    for(int i=1;i<=e;i++)scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].w);

排序

sort(a+1,a+e+1,cmp);

就只有這么一行。
sort其實是algorithm頭文件的一個函數(shù),用來排序,后面我會專門有一篇文章來講它 。
cmp是一個函數(shù),用來排序。

bool cmp(node x,node y){//注意開結構體類型
    if(x.w<y.w)return 1;//如果邊 x的長度小于邊y的長度,函數(shù)返回真,也就是要交換的意思
    if(x.w==y.w)//如果邊的長度相同(只是為了判重)
        if(x.x>y.x)return 1;//返回 起點更大的
    return 0;
}

主程序

for(int i=1;i<=e;i++)
{
        if(getfather(a[i].x)!=getfather(a[i].y))
    {//如果點 x與點y不在同一個集合里
            ans+=a[i].w;//把這條邊 的長度加入總和
            dad[getfather(a[i].x)]=a[i].y;//并 集過程
            p++;//p記錄邊的數(shù)量
        }
   }//因為題目數(shù)據(jù),我就直接遍歷了所有邊

最后輸出

cout<<ans;//輸出總和

還是很簡單吧?
完整代碼:

#include <bits/stdc++.h>
using namespace std;
const int M=200100;
struct node{
    int x;
    int y;
    int w;
}a[M];
int n,e,dad[M],p=1,ans;

bool cmp(node x,node y){
    if(x.w<y.w)return 1;
    if(x.w==y.w)
        if(x.x>y.x)return 1;
    return 0;
}
int getfather(int x){
    if(x==dad[x])return x;
    dad[x]=getfather(dad[x]);
    return dad[x];
}
    
int main()
{
    cin>>n>>e;
    for(int i=1;i<=e;i++)scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].w);
    sort(a+1,a+e+1,cmp);
    for(int i=1;i<=n;i++)dad[i]=i;
    for(int i=1;i<=e;i++){
        if(getfather(a[i].x)!=getfather(a[i].y)){
            ans+=a[i].w;
            dad[getfather(a[i].x)]=a[i].y;
            p++;
        }
    }
    cout<<ans;
    return 0;
}
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • 參見貪心算法——最小生成樹算法 目錄 1 最小生成樹問題 2 貪心選擇性質(zhì)2.1 貪心選擇框架——選擇安全邊2.2...
    王偵閱讀 3,897評論 0 2
  • 前言 其實讀完斯坦福的這本《互聯(lián)網(wǎng)大規(guī)模數(shù)據(jù)挖掘》,讓我感覺到,什么是人工智能?人工智能就是更高層次的數(shù)據(jù)挖掘。機...
    我偏笑_NSNirvana閱讀 13,125評論 1 23
  • 這篇文章由 最小生成樹-Prim算法和Kruskal算法 整理而來, 感謝這篇文章的作者 Prime算法 1. 概...
    愛上落入塵世間的你閱讀 4,352評論 0 2
  • 一、定義 最小生成樹(Minimum Spanning Tree,MST)僅針對加權連通無向圖。對于一副加權連通無...
    null12閱讀 2,550評論 0 0
  • 最小生成樹是一個連通加權無向圖中一棵權值最小的生成樹。 Prim算法思想:設圖G頂點集合為U,首先任意選擇圖G中的...
    乘瓠散人閱讀 1,426評論 0 0

友情鏈接更多精彩內(nèi)容