洛谷P3366 【模板】最小生成树.Kruskal算法

题目:https://www.luogu.com.cn/problem/P3366

 

Kruskal算法:

通过边从小到大排序,若所选的边与已选的边不成环(并查集实现),则选上。

 

C语言:

 排序用qsort(a, num, sizeof(a的类型),cmp):

_a,_b指针传入,再通过(Node*)切换格式,再通过*取值.

int cmp(void* _a, void* _b)
{
    Node a = *(Node*) _a;
    Node b = *(Node*) _b;
    return a.weight - b.weight;
}

 

并查集:

find()找父节点:

int find(int fa[], int x)
{
    int r = x, i = x, temp;

    while (fa[r] != r)
    {
        r = fa[r];
    }

    while (i != r)
    {
        temp = fa[i];
        fa[i] = r;
        i = temp;
    }
    return r;
}

完整代码:

#include <stdio.h>
#include <stdlib.h>

typedef struct node
{
    int from, end, weight;
}Node;

int cmp(void* _a, void* _b)
{
    Node a = *(Node*) _a;
    Node b = *(Node*) _b;
    return a.weight - b.weight;
}

int find(int fa[], int x)
{
    int r = x, i = x, temp;

    while (fa[r] != r)
    {
        r = fa[r];
    }

    while (i != r)
    {
        temp = fa[i];
        fa[i] = r;
        i = temp;
    }
    return r;
}

void kruskal(Node edge[], int fa[], int n, int m)
{
    int i = 0, tot, ans = 0, fx, fy;

    tot = 0;
    while (tot < n - 1 && i < m)
    {
        fx = find(fa, edge[i].from);
        fy = find(fa, edge[i].end);

        if (fx != fy)
        {
            fa[fx] = fy;
            ans += edge[i].weight;
            tot += 1;
        }
        i += 1;
    }
    if (tot < n - 1)
        printf("orz");
    else
        printf("%d", ans);
}


int main()
{
    int i, n, m, x, y, z;
    Node edge[200005];
    int fa[5005];

    scanf("%d%d", &n, &m);
    for (i = 0; i < m; i++)
    {
        scanf("%d%d%d", &x, &y, &z);
        edge[i].from = x;  edge[i].end = y;   edge[i].weight = z;//只存单向
    }

    qsort(edge, m, sizeof(Node), cmp);

    /*for (i = 0; i < m; i++)
        printf("%d\n", edge[i].weight);*/

    for (i = 1; i <= n; i++)
        fa[i] = i;
    kruskal(edge, fa, n, m);

    return 0;
}

 

Python:

结构体数组排序:

Edg.sort(key=lambda edge: edge.weight)
#lambda edge是自己设的,是Edg[]的一个元素,并按照edg.weight从小到大排序

 

代码:

class Edge(object):
    def __init__(self, x, y, z):
        self.begin = x
        self.end = y
        self.weight = z

def find(x):
    global fa
    r = x
    while fa[r] != r:
        r = fa[r]
    i = x
    while i != r:
        temp = fa[i]
        fa[i] = r
        i = temp
    return r

def Kruskal():
    global fa, Edg, n, m
    tot = 0
    i = 0
    ans = 0

    while tot < n - 1 and i < m:
        fx = find(Edg[i].begin)
        fy = find(Edg[i].end)
        if fx != fy:
            fa[fx] = fy
            tot += 1
            ans += Edg[i].weight
        i += 1
    if tot < n - 1:
        print("orz")
    else:
        print(ans)


s = input()
n, m = s.split(' ')
n = int(n)
m = int(m)
Edg = []
for i in range(m):
    s = input()
    x, y, z = s.split(' ')
    x = int(x)
    y = int(y)
    z = int(z)
    Edg.append(Edge(x, y, z))


Edg.sort(key=lambda edge: edge.weight)

fa = [0 for i in range(n + 5)]
for i in range(1, n + 1):
    fa[i] = i
Kruskal()

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值