Kruskal算法

Kruskal算法實際上是 貪心+並查集的結合,只要會了並查集,那麼這個算法一點難度都沒有了,,,

下來是講解下這個算法的具體實現步驟和時間複雜度,,首先,對於一個具有n個頂點的圖,我們知道至少會有n-1條邊,使這個圖不構成迴路,好了,那麼這n-1條邊剛好可以構成一棵樹,既然要求造價最小的一棵樹,那麼我們就利用貪心的思想,先對每一條邊的權值進行從小到大排序,然後,依次從小到大開始選邊,選出來的邊在這支離破碎的n個頂點上進行樹的構建,如果我們在連邊的過程中遇到了兩個頂點同屬於一個集合的情況,那麼我們就利用並查集來預先判定,,讓這種情況儘量不要發生,,,通過MlogM的時間,我們就可以構成這棵最小生成樹了。。

代碼:

# include<cstdio>
# include<iostream>
# include<algorithm>
# include<cstring>
# include<string>
# include<cmath>
# include<queue>
# include<stack>
# include<set>
# include<map>

using namespace std;

# define inf 999999999
# define MAX 2333

int f[10];
int n,m;
int ans;
int cnt;

struct edge
{
    int u;
    int v;
    int w;
}e[MAX];

int cmp ( edge a,edge b )
{
    return a.w < b.w;
}

int getf( int v )
{
    if ( f[v]==v )
        return v;
    else
    {
        f[v] = getf( f[v] );
        return f[v];
    }
}

int merge ( int v,int u )
{
    int t1 = getf(v);
    int t2 = getf(u);
    if ( t1!=t2 )
    {
        f[t2] = t1;
        return 1;
    }
    return 0;
}


int main(void)
{
    cin>>n>>m;
    for ( int i = 1;i <= m;i++ )
    {
        cin>>e[i].u>>e[i].v>>e[i].w;
    }
    sort(e+1,e+1+m,cmp);
   
    for ( int i = 1;i <= n;i++ )
    {
        f[i] = i;
    }

    for ( int i = 1;i <= m;i++ )
    {
        if ( merge( e[i].u , e[i].v ) )
        {
            cnt++;
            ans+=e[i].w;
        }
        if ( cnt == n-1 )
        {
            break;
        }
    }

    cout<<ans<<endl;

	return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章