现在的位置: 首页 > 综合 > 正文

Kruskal算法

2018年04月28日 ⁄ 综合 ⁄ 共 1001字 ⁄ 字号 评论关闭

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;
}

抱歉!评论已关闭.