【算法】最小生成树的解法

71人阅读 评论(3) 收藏 举报
分类:

最小生成树


定义

关于N个点用其中的N-1条边连起来的权值最小的图


算法

prim

类似Dijkstra和贪心的思路
1. 取一个点为起点遍历所有与其连接的点
2. 把最小权值的点加入最小生成树
3. 修改于其相连的点权值
4. 重复1,2,3直到N次循环
例题:
洛谷P3366:最小生成树模板

https://www.luogu.org/problemnew/show/P3366

代码:

#include<iostream>
#include<cstring>
using namespace std;
int g[5005][5005];
int minn[200001];//存蓝点i与白点相连的最小边 
bool exist[5005];//判断是否加入树中 
int n,m,x,y,z;
int tot;
int main()
{
    cin>>n>>m;
    memset(g,127,sizeof(g));
    for(int i=1;i<=m;i++)
    {
        cin>>x>>y>>z;
        //g[x][y]=z;
        //g[y][x]=z;原程序 
        if(z<g[x][y])// 这题有重边所以取最小的边 
        g[x][y]=g[y][x]=z;
    }
    memset(minn,127,sizeof(minn));
    minn[1]=0;//从1开始 
    for(int i=1;i<=n;i++)
    {
        int k=0;
        for(int j=1;j<=n;j++)
        {
            if(exist[j]==0&&minn[k]>minn[j])//找到与白点相连的最小蓝点 
            k=j;
        }
        exist[k]=1;//将蓝点k加入树中 标记为白点 
        tot+=minn[k];//计算权值和 
        for(int j=1;j<=n;j++)
        {
            if(exist[j]==0&&g[k][j]<minn[j])//修改与k相连所有的蓝点 
            minn[j]=g[k][j];
        }
    }
    cout<<tot;
}

kruskal

  1. 把边用万能的sort从小到大排一遍
  2. 从小到大挑边合并运用并查集的思路直到有N-1条边
    并查集blog:

https://blog.csdn.net/broken_string_/article/details/79947105

代码:
例题同上

#include<iostream>
#include<algorithm>
using namespace std;
struct edge
{
    int l,r,w;//左端点 右端点 权值 
}e[200001];
int father[5001];
int n,m,k=0,tot;
bool cmp(const edge &a,const edge &b)//用权值排序 
{
    if (a.w<b.w) return 1;
    else return 0;
}
int find(int x)
{
    if(father[x]!=x)
    father[x]=find(father[x]);
    return father[x];
}
void unionn(int x,int y)
{
    int fa=find(x);
    int fb=find(y);
    if(fa!=fb)
    father[fa]=fb;
}
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    father[i]=i;
    for(int i=1;i<=m;i++)
    {
        cin>>e[i].l>>e[i].r>>e[i].w;
    }
    sort(e+1,e+1+m,cmp);
    for(int i=1;i<=m;i++)
    {
        if(find(e[i].l)!=find(e[i].r))
        {
            unionn(e[i].l,e[i].r);
            tot+=e[i].w;
            k++;
        }
        if(k==n-1) break;//到n-1条时退出 
    }
    cout<<tot;
}
查看评论

最小生成树算法汇总

较为完全的初学者学习最小生成树的利器,想要玩转ACM的小编倾情奉献
  • ltyqljhwcm
  • ltyqljhwcm
  • 2016-07-28 15:38:29
  • 2524

最小生成树 《啊哈算法》读书笔记

最小生成树:任何只由G的边构成,并包含G的所有顶点的树称为G的生成树(G连通). 加权无向图G的生成树的代价是该生成树的所有边的代码(权)的和. 最小代价生成树是其所有生成树中代价最小的生成树。   ...
  • huatian5
  • huatian5
  • 2016-07-08 14:18:59
  • 1026

最小生成树Kruskalsh算法)

  • 2010年04月09日 11:09
  • 173KB
  • 下载

最小生成树的3个算法

最小生成树——Prim、Kruskal、Sollin(Boruvka)   本文内容框架: 1.Prim算法及其基于优先队列实现       2.Kruskal算法   ...
  • DJS_K_D
  • DJS_K_D
  • 2015-08-31 11:16:31
  • 2365

算法之详解最小生成树

算法之详解最小生成树 分类: Algorithms & Data Structure2012-05-01 00:20 9160人阅读 评论(31) 收藏 举报 算法algorith...
  • u014774781
  • u014774781
  • 2015-06-12 20:02:18
  • 1905

最小生成树的两种算法:Prim和Kruskal算法

越来越明白了一个道理:你写不出代码的原因只有一个,那就是你没有彻底理解这个算法的思想!! 以前写过最小生成树,但是,水了几道题后,过了一段时间,就会忘却,一点也写不出来了。也许原因只有一个,那就是我没...
  • I_am_a_winer
  • I_am_a_winer
  • 2015-04-25 22:42:28
  • 1633

bzoj3058 四叶草魔杖(状压dp+最小生成树)

正解是最小生成树+状压dp。暴力的求出每个集合的和,若为0,则对这个集合做最小生成树,它的mst就是使得这个集合的点都合法的代价。然后如果s1,s2两个集合不重复,且都可以合法,则s1与s2的并集也可...
  • Icefox_zhx
  • Icefox_zhx
  • 2018-01-13 20:53:09
  • 90

最小生成树-MST算法详解及代码实现

最小生成树,贪心算法,Kruskal,Prim算法
  • coder_oyang
  • coder_oyang
  • 2015-09-03 16:34:05
  • 5166

浅谈最小生成树的算法思路(一)Prim算法

Prim算法是求最小生成树的一种常见算法,简单谈一下笔者自己的理解。算法思路 设已经确定的点集为P,初始为空。设还未确定的点集为Q,初始为该图所有点的集合。设已经确定的边为X,初始为空。 选取任意一点...
  • Lnho2015
  • Lnho2015
  • 2016-02-16 17:04:03
  • 1523

最小生成树-两种算法复杂度比较 poj-1258,2485

1.Prim算法 时间是复杂度O(n2),适合稠密图。 例:Poj–1258 题目大意:n个城市建造光缆,要使这些城市直接通信,并且光缆费用最小。 #include #include #de...
  • jichangzhen
  • jichangzhen
  • 2016-08-20 11:37:47
  • 1489
    个人资料
    持之以恒
    等级:
    访问量: 391
    积分: 164
    排名: 110万+
    文章存档
    最新评论