码迷,mamicode.com
首页 > 其他好文 > 详细

最小生成树

时间:2020-01-20 12:49:39      阅读:68      评论:0      收藏:0      [点我收藏+]

标签:就是   包含   +=   get   模板   const   ref   连通   sum   

最小生成树

最小生成树就是在一个图中寻找一个联通图,必须包含原图的所有节点,且这个图的所有边的权值和最小.
为什么是一个树呢?因为只要求联通,就一定没有环,没有环不就是树了嘛!

Kruskal算法

Kruskal算法的核心是加边和判环.一条一条把边加上,如果加上会形成环就不加,最后弄成一个连通图.

假设有n个节点,就需要加(n-1)条边.为什么呢?因为每加上一条边,就会多连接一个点.
因为是要求最小生成树,所以先将所有边权值从小到大排序,挨个加边,加完的值一定是最小的.
判环主要用并查集实现,若两个节点的祖先不同,则加边后不会形成环,反之会形成环.

P3366 【模板】最小生成树

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>

using namespace std;
int n,m,p,sum,father[5005];
struct Edge
{
    int x,y,w;
}a[200005];
int getfather(int);
void merge(int,int);
bool cmp(const Edge &a,const Edge &b);

int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++) father[i]=i;
    for(int i=1;i<=m;i++)
    { 
        cin>>a[i].x>>a[i].y>>a[i].w;
    }
    sort(a+1,a+m+1,cmp);
    int k=0;
    for(int i=1;i<=m;i++)
    {
        if(getfather(a[i].x)!=getfather(a[i].y))
        {
            ++k;
            merge(a[i].x,a[i].y);
            sum+=a[i].w;
        }
        if(k==n-1) break;
    }
    cout<<sum;
    
    return 0;
}

int getfather(int v)
{
    if(father[v]!=v) father[v]=getfather(father[v]);
    return father[v];
} 

void merge(int a,int b)
{
    father[getfather(a)]=getfather(b);
}

bool cmp(const Edge &a,const Edge &b)
{
    return a.w<b.w; 
}

Prim算法

核心:加点
(未完待续)

最小生成树

标签:就是   包含   +=   get   模板   const   ref   连通   sum   

原文地址:https://www.cnblogs.com/huaruoji/p/12217305.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!