图论笔记3:最小生成树

最小生成树笔记1:Kruskal

一、算法原理

kruskal算法是一种基于贪心思想的算法,将每一条边排序,然后从小到大依此选择,能选则选,若不能选则下一个,直到每个点都被选中。其中,有无被选中用并查集来判断。
将每条边看成一棵树,若两个点在同一个边上,则看这两个点是不是在同一个树上,若不是就可以通过这个最小的可以连接这两颗树的边(因为是从小到大选的,所以如果有比它更小的边,则会被提前选中),如此反复就可以找到最小的一棵树。

二、算法模板

int fa[100005];
int n, m;
struct Edge
{
    int u, v, w;
    friend bool operator<(Edge a, Edge b)
    {
        return a.w < b.w;
    }
} e[500005];
int find(int x)
{
    if (fa[x] == 0)
        return x;
    return fa[x] = find(fa[x]);
}
int solve()
{
    int u, v, w, ans = 0;
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
        fa[i] = 0;
    for (int i = 1; i <= m; i++)
        cin >> e[i].u >> e[i].v >> e[i].w;
    sort(e + 1, e + 1 + m);
    int cnt = 0;
    for (int i = 1; i <= m; i++)
    {
        int q = find(e[i].u), p = find(e[i].v);
        if (p == q)
            continue;
        cnt++;
        ans += e[i].w;
        fa[q] = p;
        if (cnt == n - 1)
            break;
    }
    return ans;
}

算法总结

时间复杂度和把所有边排序的复杂度一样,为O(mlogm)。
如果只需要求最小生成树的最大边的权值,可以在O(m)的时间内求出。

最小生成树笔记2 :prim

一、算法原理

和dijkstra算法类似都是一个点一个点找最小边长,有所不同的是,prim的dis数组是用来更新最小边,而dijkstra是用来更新最短路径

二、算法模板


int maps[105][105];
int dis[105];
bool bj[105];
int prim(int m)
{
    for (int i = 1; i <= m; i++)
        dis[i] = 0x3f3f3f3f;
    for (int i = 1; i <= m; i++)
        bj[i] = 0;
    int ans = 0;
    for (int i = 1; i <= m; i++)
    {
        int v = -1;
        for (int j = 1; j <= m; j++)
        {
            if (!bj[j] && (v == -1 || dis[j] < dis[v]))
                v = j;
        }
        if (i != 1 && dis[v] == 0x3f3f3f3f)
            return 0x3f3f3f3f;
        if (i != 1)
            ans += dis[v];
        bj[v] = 1;
        for (int j = 1; j <= m; j++)
            dis[j] = min(dis[j], maps[v][j]);
    }
    return ans;
}

算法总结

和dijkstra算法差不多,所以复杂度一样都是O(n²)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值