最小生成树--kruskal

1.算法简介

    (Prim在稠密图中比Kruskal优,在稀疏图中比Kruskal劣。

    ·这个算法显然是一个用来找最小生成树的算法

    ·给一个无向图,这个无向图有N个点,M个边

    ·首先把边按边权排个序

    ·然后用这些边从小到大连起来

    ·如果出现环则不连这条边(用并查集

    ·连了N-1条边后(即已经构造好最小生成树后)退出

     Input

    第一行包含两个整数N、M,表示该图共有N个结点和M条无向边。(N<=5000,M<=200000)

    接下来M行每行包含三个整数Xi、Yi、Zi,表示有一条长度为Zi的无向边连接结点Xi、Yi

       Output

    输出包含一个数,即最小生成树的各边的长度之和;

扫描二维码关注公众号,回复: 1062388 查看本文章

2.  问题分段

    ·构造结构体

    
    struct edge
    {
    	int u,v,w;
    } a[M];

    ·将边排序(手打sort

    
    void swap(int &x,int &y)
    {
    	int tmp=x;
    	x=y;y=tmp;
    }
    void qsort(int l,int r)
    {
       	int i=l,j=r,mid=a[(l+r)/2].w;
	while(i<j)
	{
		while(a[i].w<mid) i++;
		while(mid<a[j].w) j--;
		if(i<=j)
		{
			swap(a[i].u,a[j].u);
			swap(a[i].v,a[j].v);
			swap(a[i].w,a[j].w);
			i++;j--;
		}
	}
	if(i<r) qsort(i,r);
	if(l<j) qsort(l,j);
    }

     ·并查集

        1.初始化

            for(int i=1;i<=n;i++) f[i]=i;

        2.找父节点函数

         

         int getf(int x)

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

        3.连边

            int cnt=0;
             for(int i=1;i<=m;i++)
             {
              if(getf(a[i].u)!=getf(a[i].v))
              {
               ans+=a[i].w;
               f[getf(a[i].v)]=a[i].u;
               cnt++;
               if(cnt==n-1) break;
              }
	   }

3.代码实现

 
 
    #include<iostream>
    #include<cstdio>
    using namespace std;
    const int N=5005;
    const int M=200005;
    int f[N];
    struct edge
    {
    	int u,v,w;
    } a[M];
    int n,m,ans;
    void swap(int &x,int &y)
    {
    	int tmp=x;
    	x=y;y=tmp;
    }
    void qsort(int l,int r)
    {
    	int i=l,j=r,mid=a[(l+r)/2].w;
    	while(i<j)
	{
		while(a[i].w<mid) i++;
		while(mid<a[j].w) j--;
		if(i<=j)
		{
			swap(a[i].u,a[j].u);
			swap(a[i].v,a[j].v);
			swap(a[i].w,a[j].w);
			i++;j--;
		}
	}
	if(i<r) qsort(i,r);
	if(l<j) qsort(l,j);
    }
    int getf(int x)
    {
	    if(f[x]==x)
	    {
	    	return x;
	    }
	    else 
	    {
	    	f[x]=getf(f[x]);
		return f[x];
	    }
    }
    int main()
    {
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++)
		scanf("%d%d%d",&a[i].u,&a[i].v,&a[i].w);
	qsort(1,m);
	for(int i=1;i<=n;i++) f[i]=i;
	int cnt=0;
	for(int i=1;i<=m;i++)
	{
		if(getf(a[i].u)!=getf(a[i].v))
		{
			ans+=a[i].w;
			f[getf(a[i].v)]=a[i].u;
			cnt++;
			if(cnt==n-1) break;
		}
	}
	printf("%d\n",ans);
	return 0;
    }


猜你喜欢

转载自blog.csdn.net/salix_leaf/article/details/80383569