欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++實現(xiàn)基于不相交集合的O(mlgn)復雜度的kruskal算法

 更新時間:2023年02月22日 14:46:17   作者:Shawn-Summer  
這篇文章主要為大家詳細介紹了C++如何實現(xiàn)基于不相交集合的O(mlgn)復雜度的kruskal算法,文中的示例代碼講解詳細,感興趣的小伙伴可以了解一下

C++實現(xiàn)基于不相交集合的O(mlgn)復雜度的kruskal算法

本文實現(xiàn)完全參考<<Introduction to Algorithms Third edition>>,

不相交集合的數(shù)據(jù)結(jié)構(gòu)

我們采用森林的方式實現(xiàn)不相交集合。這個森林是極簡化的,每個節(jié)點只有一個指向父親的指針,而且森林中的每一顆樹都是一個集合,我們?nèi)涞母?jié)點為這個集合的代表元。

int rank[505];
int father[505];
void make_set(int x)
{
	father[x]=x;
	rank[x]=0;
}
int find_set(int x)
{
    if (x!=father[x])
    {
        father[x]=find_set(father[x]);
    }
    return father[x];
}
void simply_union_set(int u,int v)
{
    u=find_set(u);
    v=find_set(v);
    father[u]=v;
}
void  perfect_union_set(int u,int v)
{
    u=find_set(u);
    v=find_set(v);
    if (rank[u]>rank[v])
    {
        father[v]=u;
    }
    else
    {
        father[u]=v;
        if(rank[u]==rank[v])
        rank[v]++;
    }

}

可以看到在find_set()函數(shù)中采用了兩趟遍歷的思想,第一趟遍歷找的根節(jié)點,第二趟遍歷將路徑上的節(jié)點全部指向根節(jié)點,完成了壓縮樹高。

在實現(xiàn)集合合并的時候,我們采用了兩種方法:一種方法是直接合并simply_union_set,另一種是采用按秩合并的思想perfect_union_set,即總是讓秩小合并到秩大的集合中,這是一種減少樹高的有效策略;

當我們采用按秩合并時時,上述每一個操作的最差時間復雜度,都約等于O(1)

詳情見<<Introduction to Algorithms Third edition>>中證明

kruskal 算法

void kruskal()
{
    for(int i=0;i<num_v;i++)make_set(i);
    sort(arr_edge.begin(),arr_edge.end(),mycompare);
    for(int i=0;i<arr_edge.size();i++)
    {
        int fr=arr_edge[i].fr;
        int to=arr_edge[i].to;
        int w=arr_edge[i].w;
        if( find_set(fr)!=find_set(to))
        {
        	result+=w;
            perfect_union_set(fr,to);
        }
    }
}

kruskal 算法是一種基于貪心策略的算法,它的時間復雜度的最大開銷就是排序算法,即O(mlgm)=O(mlgn),這里m表示邊數(shù),n表示頂點數(shù)

知識補充

乘勝追擊一下,通過一個例題再深入了解一下kruskal 算法吧

題目http://poj.org/problem?id=2485

思路:就是最小生成樹啊

代碼

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<vector>
using namespace std;
#define INTMAX 0x3f3f3f3f
typedef pair<int,int> pii;
typedef long long ll;
#define x first
#define y second

int rank[505];
int father[505];
int find_set(int x)
{
    if (x!=father[x])
    {
        father[x]=find_set(father[x]);
    }
    return father[x];
}
void simply_union_set(int u,int v)
{
    u=find_set(u);
    v=find_set(v);
    father[u]=v;
}
void  perfect_union_set(int u,int v)
{
    u=find_set(u);
    v=find_set(v);
    if (rank[u]>rank[v])
    {
        father[v]=u;
    }
    else
    {
        father[u]=v;
        if(rank[u]==rank[v])
        rank[v]++;
    }

}
struct edge
{
    int fr,to,w;
};
int num_case,num_v,result;
vector<edge> arr_edge;

void debug()
{
    for(int i=0;i<arr_edge.size();i++)
    {
        cout<<arr_edge[i].fr<<" to "<<arr_edge[i].to<<"="<<arr_edge[i].w<<endl;
    }
}

void init()
{
    arr_edge.clear();
    result=0;
}
void input()
{
    int w;
    scanf("%d",&num_v);
    for(int i=0;i<num_v;i++)
    {
        for(int j=0;j<num_v;j++)
        {
            scanf("%d",&w);
            if(i<j)
            {
                edge temp;
                temp.fr=i;
                temp.to=j;
                temp.w=w;
                arr_edge.push_back(temp);
            }
        }
    }

}
bool mycompare(const edge& x,const edge &y)
{
    return x.w<y.w;
}
void kruskal()
{
    for(int i=0;i<num_v;i++)father[i]=i;
    sort(arr_edge.begin(),arr_edge.end(),mycompare);
    for(int i=0;i<arr_edge.size();i++)
    {
        int fr=arr_edge[i].fr;
        int to=arr_edge[i].to;
        int w=arr_edge[i].w;
        if( find_set(fr)!=find_set(to))
        {
            result=max(result,w);
            simply_union_set(fr,to);
        }
    }
}
void solve()
{
    init();
    input();
    //debug();
    kruskal();
    cout<<result<<endl;
}

int main()
{
    scanf("%d",&num_case);
    while(num_case--)
    {
        solve();
    }
    return 0;
}

到此這篇關(guān)于C++實現(xiàn)基于不相交集合的O(mlgn)復雜度的kruskal算法的文章就介紹到這了,更多相關(guān)C++ kruskal算法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 帶你從頭學習C++的封裝

    帶你從頭學習C++的封裝

    這篇文章主要為大家從頭學習了C++的封裝,使用數(shù)據(jù)庫,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • C++中如何使用引用避免內(nèi)存復制

    C++中如何使用引用避免內(nèi)存復制

    C++引用是一種強大的工具,可以避免在函數(shù)調(diào)用過程中發(fā)生的常見內(nèi)存復制問題,本文主要介紹了C++中如何使用引用避免內(nèi)存復制,感興趣的可以了解一下
    2023-10-10
  • VC++實現(xiàn)文件與應用程序關(guān)聯(lián)的方法(注冊表修改)

    VC++實現(xiàn)文件與應用程序關(guān)聯(lián)的方法(注冊表修改)

    這篇文章主要介紹了VC++實現(xiàn)文件與應用程序關(guān)聯(lián)的方法,涉及VC++針對注冊表的相關(guān)操作技巧,需要的朋友可以參考下
    2016-08-08
  • 淺談C++不同繼承之間的關(guān)系

    淺談C++不同繼承之間的關(guān)系

    本文主要介紹了淺談C++不同繼承之間的關(guān)系,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-04-04
  • C++的array和&array有什么區(qū)別

    C++的array和&array有什么區(qū)別

    本文主要介紹了C++的array和&array有什么區(qū)別,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-08-08
  • C++實現(xiàn)哈夫曼樹的方法

    C++實現(xiàn)哈夫曼樹的方法

    這篇文章主要為大家詳細介紹了C++實現(xiàn)哈夫曼樹的方法,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-04-04
  • C++實現(xiàn)基于控制臺界面的吃豆子游戲

    C++實現(xiàn)基于控制臺界面的吃豆子游戲

    這篇文章主要介紹了C++實現(xiàn)基于控制臺界面的吃豆子游戲,實例分析了吃豆子游戲的原理與C++實現(xiàn)技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-04-04
  • C++實現(xiàn)自頂向下的歸并排序算法

    C++實現(xiàn)自頂向下的歸并排序算法

    這篇文章主要介紹了C++實現(xiàn)自頂向下的歸并排序算法,結(jié)合實例詳細分析了自頂向下的歸并排序算法的原理與具體實現(xiàn)步驟,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-12-12
  • C++STL教程之vector模板的使用

    C++STL教程之vector模板的使用

    模板類vector是一個動態(tài)數(shù)組,類似于string類,可存放任意類型,能夠末尾、中間增加數(shù)據(jù),基本上是是new創(chuàng)建動態(tài)數(shù)組的替代品,vector可以自動完成new和delete
    2022-08-08
  • c語言之如何求e的近似值

    c語言之如何求e的近似值

    這篇文章主要介紹了c語言之如何求e的近似值問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-12-12

最新評論