月球美容计划之最小生成树(MST)

寒假学的两个算法,普里姆,克鲁斯卡尔终于弄明白了,可以发总结了

先说说普里姆,它的本质就是贪心,先从任意一个点开始,找到最短边,然后不断更新更新len数组,然后再选取最短边并标记经过的点,直到所有的点被标记,或者说已经选好了n-1条边。

拿SDUTOJ2144为例,代码如下,可做模板

#include <stdio.h>
#include <string.h>
#define INF 1000000

//最小生成树
//普里姆

int G[200][200];
int len[200];
bool vis[200];

int prm (int n)
{
    int i,k,ans = 0;
    memset (vis,0,sizeof(vis));

    for (i = 2;i <= n;i++)//初始化
        len[i] = G[1][i];
    vis[1] = 1;
    for (i = 1;i < n;i++) //循环n - 1次
    {                     //因为n个顶点的MST一定是n-1条边
        int imin = INF,xb;
        for (k = 1;k <= n;k++)
            if (!vis[k] && imin > len[k])
            {
                imin = len[k];
                xb = k;
            }

        if (imin == INF)  //没有找到最小值,说明图不连通
            return -1;

        vis[xb] = 1;
        ans += imin;

        for (k = 1;k <= n;k++)
            if (!vis[k] && len[k] > G[xb][k])
                len[k] = G[xb][k];
    }

    return ans;
}

int main()
{
    int n,m;

    while (~scanf ("%d%d",&n,&m))
    {
        int i,k;

        for (i = 1;i <= n;i++)
            for (k = 1;k <= n;k++)
                if (i != k)
                    G[i][k] = INF;
                else
                    G[i][k] = 0;

        for (i = 0;i < m;i++)
        {
            int a,b,c;
            scanf ("%d%d%d",&a,&b,&c);
            if (G[a][b] > c)       //如果有边多次录入,选权最小的那个
                G[a][b] = G[b][a] = c;
        }

        int ans = prm(n);

        printf ("%d\n",ans);
    }
    return 0;
}

克鲁斯卡尔,一个排序一个并查集只是表面,实质还是贪心,只不过普里斯是任选一个点选最短路,而克鲁斯卡尔是看全局,全体边排序,当然,因为排序,导致时间复杂度不容易降下来。

同样的题,代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define INF 1000000

//最小生成树
//克鲁斯卡尔

int vis[200];
struct eg
{
    int v,u,w;
}e[100000];
int cont;

int cmp (const void *a,const void *b)
{
    struct eg *ta = (struct eg *)a;
    struct eg *tb = (struct eg *)b;

    return ta->w - tb->w;
}

int fin (int a)
{
    int r = a;

    while (vis[r] != r)
        r = vis[r];
    int k;
    while (vis[a] != a)
    {
        k = vis[a];
        vis[a] = r;
        a = vis[k];
    }
    return r;
}

int add (int a,int b)
{
    vis[fin(a)] = fin (b);
    return 0;
}

int kls(int n,int m)
{
    int i;
    int ans = 0;

    for (i = 0;i <=n;i++)
        vis[i] = i;

    for (i = 0;i < m;i++)
    {
        if (fin(e[i].u) != fin(e[i].v))
        {
            add (e[i].u,e[i].v);
            ans += e[i].w;
        }
    }

    return ans;
}

int main()
{
    int n,m;

    while (~scanf ("%d%d",&n,&m))
    {
        cont = 0;
        int i,k;
        for (i = 0;i < m;i++)
        {
            int a,b,c;
            scanf ("%d%d%d",&a,&b,&c);
            //如果有边多次录入,选权最小的那个
            int tf = 1;
            for (k = 0;k < cont;k++)
            {
                if ((e[k].u == a && e[k].v == b) || (e[k].u == b && e[k].v == a))
                {
                    tf = 0;
                    if (e[k].w > c)
                        e[k].w = c;
                }
            }

            if (tf)
            {
                e[cont].u = a;
                e[cont].v = b;
                e[cont++].w = c;
            }
        }
        qsort(e,cont,sizeof(e[0]),cmp);
        int ans = kls(n,m);

        printf ("%d\n",ans);
    }
    return 0;
}

月球美容计划之最小生成树(MST)

时间: 2024-10-11 00:07:18

月球美容计划之最小生成树(MST)的相关文章

月球美容计划之图的储存结构汇总

SJ图论非常流弊,为了省赛队里知识尽量广,我就直接把图continue,如今回想起来丫的全忘了,从头開始吧. 先写写图的存储,再写写最小生成树和最短路的几个经典算法,月球美容计划就能够结束了.0 0.拖了好久,还有非常多内容要写.- - 这次总结了邻接矩阵,邻接表.十字链表.邻接多重表,边集数组,这5种经常使用的图的储存结构,或许能当模板用吧. 邻接矩阵 #include <stdio.h> #include <stdlib.h> #include <string.h>

月球美容计划之最短路

那HDU的2544作为复习最短路的题目,用不同算法. 迪杰斯特拉 有点像普利姆算法的精简版,不能有负权边 #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX 99999 #define qmin(a,b) a > b ? b : a //最短路 //迪杰斯特拉 int G[200][200]; int vis[200]; int djs (int n,int s) { int

poj——2031 最小生成树(MST) Kruskal算法

poj——2031 最小生成树(MST)  Kruskal算法 Building a Space Station Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 4985   Accepted: 2503 Description You are a member of the space station engineering team, and are assigned a task in the constructio

POJ #1789 Truck History 最小生成树(MST) prim 稠密图 链式向前星

Description 题目:链接 这道题的数据集网上比较少,提供一组自己手写的数据: INPUT: 3 aaaaaaa baaaaaa abaaaaa OUTPUT: The highest possible quality is 1/2. 思路 题意比较不好理解,简而言之就是有 n 个字符串,设两个字符串之间的差异为 dis,dis 由两个字符串对应位置上不同字母的数量决定.比如串A"aaaaaaa" .串B"baaaaaa" 和串C"abaaaaa&

POJ 3026 Borg Maze【BFS+最小生成树MST】

Borg Maze Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 12014 Accepted: 3925 Description The Borg is an immensely powerful race of enhanced humanoids from the delta quadrant of the galaxy. The Borg collective is the term used to describe

NBUT 1914 asd的甩锅计划(最小生成树)

NBUT 1914 asd的甩锅计划 题目描述 大家对hdu上面的畅通工程系列一定很熟悉了吧.比如如下一段,就是畅通工程里面其中一个题的叙述. 某省调查乡村交通状况,得到的统计表中列出了任意两村庄间的距离.省政府"畅通工程"的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可),并要求铺设的公路总长度为最小.请计算最小的公路总长度. 大家觉得这种情况一定很简单而且生活中遇不到吧.然而你错了!NBUT的书记yh就遇到了这么个头疼事:asd下

最小生成树MST

Kruskal算法思想:贪心选边,用并查集维护点集. 1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 #include <cstring> 5 #include <cmath> 6 using namespace std; 7 const int maxn = 5000 + 10; 8 int n, m, f[maxn], sum = 0, tot = 0; 9

痴心不改

 2014ACM集训总结 第二次参加ACM集训,可这一次的集训感受大不同以往. 首先这假期学的内容不是那么简单,在学习和刷题的过程中,智商压制现象很严重. 其次,这个假期发生了很多事情,身边的家伙陆续的退役,其实还有我的两个队友. 所以,心中很矛盾,也很复杂,无法用语言表达,只能慢慢调整,让自己恢复正常的感觉. 最后的4场比赛,没有真心的投入,一场中途才赶到实验室,两场提前离场.总的来说,是我逃避现实,我不知道如何面对现实. 一个假期过后,该学会的没有学会,反而留下一堆乱麻,不知道从何捋起.

最小生成树--Prim算法,基于优先队列的Prim算法,Kruskal算法,Boruvka算法,“等价类”UnionFind

最小支撑树树--Prim算法,基于优先队列的Prim算法,Kruskal算法,Boruvka算法,“等价类”UnionFind 最小支撑树树 前几节中介绍的算法都是针对无权图的,本节将介绍带权图的最小支撑树(minimum spanning tree)算法.给定一个无向图G,并且它的每条边均权值,则MST是一个包括G的所有顶点及边的子集的图,这个子集保证图是连通的,并且子集中所有边的权值之和为所有子集中最小的. 本节中介绍三种算法求解图的最小生成树:Prim算法.Kruskal算法和Boruvk