POJ-图论-最小生成树模板

POJ-图论-最小生成树模板php

Kruskal算法算法

1.初始时全部结点属于孤立的集合。数组

2.按照边权递增顺序遍历全部的边,若遍历到的边两个顶点仍分属不一样的集合(该边即为连通这两个集合的边中权值最小的那条)则肯定该边为最小生成树上的一条边,并将这两个顶点分属的集合合并。数据结构

3.遍历完全部边后,原图上全部结点属于同一个集合则被选取的边和原图中全部结点构成最小生成树;不然原图不连通,最小生成树不存在。ide

数据结构:引入边结构,并重载小于号运算符spa

struct Edge
{
    int a, b;//边的两端结点编号
    int cost;//边的权值
    bool operator <(const Edge &A)const
    {
        return cost < A.cost;//边权从小到大排列
    }
}edge[6000];

用并查集来实现集合操做code

void init()
{
    for (int i = 1; i <= n; i++)p[i] = i;
    ans = 0;
}

int find(int x)
{
    return (x == p[x]) ? x : p[x] = find(p[x]);
}

void Union(int i)//以边为单位合并
{
    int a = find(edge[i].a);
    int b = find(edge[i].b);//查找边的两个顶点所在集合的信息
    if (a != b) //若他们属于不一样集合,则选用该边
    {
        p[b] = a;//合并集合
        ans += edge[i].cost;//累加权值
    }
}

例 5.3 仍是畅通工程blog

#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 101;

int p[N];//父结点数组
int n;//结点数量
int ans;//最小权值和

struct Edge
{
    int a, b;//边的两端结点编号
    int cost;//边的权值
}edge[6000];

bool cmp(Edge a, Edge b)
{
    return a.cost<b.cost;
}

void init()
{
    for (int i = 1; i <= n; i++)p[i] = i;
    ans = 0;
}

int find(int x)
{
    return (x == p[x]) ? x : p[x] = find(p[x]);
}

void Union(int i)//以边为单位合并
{
    int a = find(edge[i].a);
    int b = find(edge[i].b);//查找边的两个顶点所在集合的信息
    if (a != b) //若他们属于不一样集合,则选用该边
    {
        p[b] = a;//合并集合
        ans += edge[i].cost;//累加权值
    }
}

int main()
{
    while (scanf("%d", &n) != EOF && n != 0)
    {
        for (int i = 1; i <= n * (n - 1) / 2; i++) scanf("%d%d%d", &edge[i].a, &edge[i].b, &edge[i].cost);
        sort(edge + 1, edge + 1 + n * (n - 1) / 2, cmp);//起始元素为edge[1],一共n * (n - 1) / 2个待排序元素
        init();
        for (int i = 1; i <= n * (n - 1) / 2; i++) Union(i);
        printf("%d\n", ans);
    }
    return 0;
}
#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 101;

int p[N];//父结点数组
int n;//结点数量
int ans;//最小权值和

struct Edge
{
    int a, b;//边的两端结点编号
    int cost;//边的权值
    bool operator <(const Edge &A)const
    {
        return cost < A.cost;//边权从小到大排列
    }
}edge[6000];

void init()
{
    for (int i = 1; i <= n; i++)p[i] = i;
    ans = 0;
}

int find(int x)
{
    return (x == p[x]) ? x : p[x] = find(p[x]);
}

void Union(int i)//以边为单位合并
{
    int a = find(edge[i].a);
    int b = find(edge[i].b);//查找边的两个顶点所在集合的信息
    if (a != b) //若他们属于不一样集合,则选用该边
    {
        p[b] = a;//合并集合
        ans += edge[i].cost;//累加权值
    }
}

int main()
{
    while (scanf("%d", &n) != EOF && n != 0)
    {
        for (int i = 1; i <= n * (n - 1) / 2; i++) scanf("%d%d%d", &edge[i].a, &edge[i].b, &edge[i].cost);
        sort(edge + 1, edge + 1 + n * (n - 1) / 2);//起始元素为edge[1],一共n * (n - 1) / 2个待排序元素
        init();
        for (int i = 1; i <= n * (n - 1) / 2; i++) Union(i);
        printf("%d\n", ans);
    }
    return 0;
}
重载Edge小于号
相关文章
相关标签/搜索