最小生成树

Posted seanocean

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最小生成树相关的知识,希望对你有一定的参考价值。

一、基本概念

  1.生成树

    在一个V个点的无向连通图中,取v-1条边,并连接所有节点所得到的子图称为生成树

  2.树的属性

    (1)有v-1条边,无环

    (2)有v-1条边,连通

    (3)任意两个点之间只有唯一一条路径连接

    (4)删除一条边后不连通

  3.最小生成树

    边权和最小的生成树

  4.最小边原则

    权值最小的边在最小生成树中

  5.唯一性定理

    对于图G,如果图中的边权值都不相同,则构成的最小生成树是唯一的

二、最小生成树算法

  1.Prim算法

技术图片

技术图片

技术图片

技术图片

技术图片

技术图片

技术图片

#include<cstdio>
#include<queue>
#include<cstring>
#include<utility>
#include<algorithm>
#define FORa(i,s,e) for(i=s;i<=e;i++)
#define R register int
using namespace std;

int n,m,cnt,ans,head[5005],dis[5005],bz[5005]; 
struct Edge

    int next,to,dis;
edge[400005];
int num_edge;
void Add_edge(int from,int to,int dis)

    edge[++num_edge]=(Edge)head[from],to,dis;
    head[from]=num_edge;

typedef pair <int,int> pp;
priority_queue <pp,vector<pp>,greater<pp> > q;//first dis     second u
void Prim()

    pp ft;
    dis[1]=0;
    q.push(make_pair(0,1));
    while(!q.empty()&&cnt<n)
    
        ft=q.top(),q.pop();
        if(bz[ft.second]) continue;
        cnt++,ans+=ft.first,bz[ft.second]=1;
        for(R i=head[ft.second];i;i=edge[i].next)
            if(dis[edge[i].to]>edge[i].dis)
                dis[edge[i].to]=edge[i].dis,q.push(make_pair(dis[edge[i].to],edge[i].to));
    

int main()

    memset(dis,127,sizeof(dis));
    R from,to,fdis;
    scanf("%d%d",&n,&m);
    for(R i=1;i<=m;i++)
    
        scanf("%d%d%d",&from,&to,&fdis);
        Add_edge(to,from,fdis),Add_edge(from,to,fdis);
    
    Prim();
    if (cnt==n)printf("%d",ans);
    else printf("orz");

 

   2.Kruskal算法

 技术图片

技术图片

技术图片

技术图片

技术图片

技术图片

#include<stdio.h>
#include<stdlib.h>
#include<algorithm>
#define LL long long 
#define FORa(i,s,e) for(int i=s;i<=e;i++)
#define FORs(i,s,e) for(int i=s;i>=e;i--)

using namespace std;
const LL N=50000,M=200000;
LL n,m,cnt,ans,num_edge,head[N+1],fa[N];
struct Edge
    LL next,from,to,dis;
    bool operator <(Edge &edge0)const
    
        return dis<edge0.dis;
    
edge[2*M+2]; 
void Add_edge(LL from,LL to,LL dis)

    edge[++num_edge]=(Edge)head[from],from,to,dis;
    head[from]=num_edge;

LL find(LL x)

    while(fa[x]!=x) x=fa[x]=fa[fa[x]];
    return x;

int main()

    LL from,to,dis;
    scanf("%lld%lld",&n,&m);
    FORa(i,1,m)
    
        scanf("%lld%lld%lld",&from,&to,&dis);
        Add_edge(from,to,dis);
    
    FORa(i,1,n) fa[i]=i;
    sort(edge+1,edge+1+m);
    FORa(i,1,m)
    
        LL t1=find(edge[i].from),t2=find(edge[i].to);
        if(t1!=t2)
        
            fa[t1]=fa[t2],ans+=edge[i].dis,cnt++;
            if(cnt==n-1) break;
        
    
    if(cnt==n-1) printf("%lld",ans);
    else printf("orz");
    return 0;

 

 

 

 

 

 

 

 

 

 

技术图片

以上是关于最小生成树的主要内容,如果未能解决你的问题,请参考以下文章

c语言最小生成树

图——最小生成树

最小生成树 求大神解救

图的最小生成树算法?

[LuoguP4208][JSOI2008]最小生成树计数(最小生成树+矩阵树定理)

最小生成树专题