首页 > 其他 > 详细

图论板子 最小生成树

时间:2019-08-01 14:02:08      阅读:57      评论:0      收藏:0      [点我收藏+]

kruskal算法 前向星+并查集 需排序(加边,还有一种加点的prim算法,不惯用,就不更了

排序后每次找权值最小的两节点组成的边,加入树,通过并查集确定公共祖先,若某边加入会出现环,跳过,直至所有点都加入树,该树即为最小生成树

板子

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<set>
#include<string>
using namespace std;
const int INF=0x3f3f3f3f;
typedef pair<int, int> pr;
typedef long long ll;
#define fi first
#define se second
#define me(x) memset(x, -1, sizeof(x))
#define mem(x) memset(x, 0, sizeof(x))
#define MAXN 500000+5
#define NIL -1
struct node
{
    int u, v, w;
}edge[MAXN];
bool cmp(node a, node b)
{
    if(a.w==b.w && a.u==b.u) return a.v<b.v;
    if(a.w==b.w) return a.u<b.u;
    return a.w<b.w;
}
int p[MAXN];//存祖先  记录每个点的前导点
int ans, n, m;

int Find(int x) //查找根节点
{
    int r=x;
    while(p[r]!=r) //根节点的上级节点为本身
        r=p[r];
    //r为根节点
    int i=x, j;
    while(p[i]!=r)//until p[p[i]]==r 路径压缩 不断更新i的上级节点为根节点
    {
        j=p[i];

        p[i]=r;   //r为根

        i=j;
    }             // 1 --> 3 --> 4 --> 5
    return r;
}

int mix() //合并 联通
{
    for(int i=0; i<m; i++)
    {
        int fx=Find(edge[i].u), fy=Find(edge[i].v);
        if(fx!=fy)
            ans+=edge[i].w, p[fx]=fy;
    }
}
int main()
{
    int i, j, k;
    while(cin>>n>>m)
    {
        ans=0;
        for(i=1; i<=n; i++)
            p[i]=i;        //初始化每个点的父节点为本身
        for(i=0; i<m; i++)
            cin>>edge[i].u>>edge[i].v>>edge[i].w;
        sort(edge, edge+m, cmp);
        mix();
        cout<<ans<<endl;
    }
}

 

图论板子 最小生成树

原文:https://www.cnblogs.com/op-z/p/11281738.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!