zoukankan      html  css  js  c++  java
  • 最小生成数kruskal算法和prim算法

    定义

    连通图:在无向图中,若任意两个顶点vivi与vjvj都有路径相通,则称该无向图为连通图。

    强连通图:在有向图中,若任意两个顶点vivi与vjvj都有路径相通,则称该有向图为强连通图。

    连通网:在连通图中,若图的边具有一定的意义,每一条边都对应着一个数,称为权;权代表着连接连个顶点的代价,称这种连通图叫做连通网。

    生成树:一个连通图的生成树是指一个连通子图,它含有图中全部n个顶点,但只有足以构成一棵树的n-1条边。一颗有n个顶点的生成树有且仅有n-1条边,如果生成树中再添加一条边,则必定成环。

    最小生成树:在连通网的所有生成树中,所有边的代价和最小的生成树,称为最小生成树。 

    kruskal算法

    此算法可以称为“加边法”,初始最小生成树边数为0,每迭代一次就选择一条满足条件的最小代价边,加入到最小生成树的边集合里。

    1. 把图中的所有边按代价从小到大排序;

    2. 把图中的n个顶点看成独立的n棵树组成的森林;

    3. 按权值从小到大选择边,所选的边连接的两个顶点ui,viui,vi,应属于两颗不同的树,则成为最小生成树的一条边,并将这两颗树合并作为一颗树。

    4. 重复(3),直到所有顶点都在一颗树内或者有n-1条边为止。

    prim算法

    此算法可以称为“加点法”,每次迭代选择代价最小的边对应的点,加入到最小生成树中。算法从某一个顶点s开始,逐渐长大覆盖整个连通网的所有顶点。

    1. 图的所有顶点集合为VV;初始令集合u={s},v=V−uu={s},v=V−u;

    2. 在两个集合u,vu,v能够组成的边中,选择一条代价最小的边(u0,v0)(u0,v0),加入到最小生成树中,并把v0v0并入到集合u中。

    3. 重复上述步骤,直到最小生成树有n-1条边或者n个顶点为止。

    kruskal算法:

    #include <iostream>
    #include <list>
    #include <vector>
    #include <algorithm>
    
    const int   INFINITE  = 0x7FFFFFFF;
    const int   VERTEX    = 6;
    const char  szVertex[] = { 'A', 'B', 'C', 'D', 'E', 'F' };
    
    struct stEdge
    {
        int u;
        int v;
        int weight;
    
        stEdge(int iu, int iv, int iweight):u(iu),v(iv),weight(iweight) {}
        
        friend bool operator<(const stEdge &a, const stEdge &b) { return a.weight < b.weight; }
    };
    
    void createGraph(int (*g)[VERTEX])
    {
        for (int i = 0; i < VERTEX; i++)
        {
            for (int j = 0; j < VERTEX; j++)
            {
                g[i][j] = INFINITE;
            }
        }
        g[0][1] = 6; g[0][2] = 1; g[0][3] = 5;
        g[1][0] = 6; g[1][2] = 5; g[1][4] = 3;
        g[2][0] = 1; g[2][1] = 5; g[2][3] = 5; g[2][4] = 6; g[2][5] = 4;
        g[3][0] = 5; g[3][2] = 5; g[3][5] = 2;
        g[4][1] = 3; g[4][2] = 6; g[4][5] = 6;
        g[5][2] = 4; g[5][3] = 2; g[5][4] = 6;
    }
    
    void initEdges(std::vector<stEdge> &edges, const int (*g)[VERTEX])
    {
        for (int i = 0; i < VERTEX; ++i)
        {
            for (int j = i+1; j < VERTEX; ++j)
            {
                edges.push_back(stEdge(i,j,g[i][j]));
            }
        }
        std::sort(edges.begin(), edges.end(), std::less<stEdge>());
    }
    
    bool notSameTree(int u, int v, std::vector<std::list<int> > &trees)
    {
        int uindex = -1, vindex = -1;
    
        for (int i = 0; i < VERTEX; ++i)
        {
            if (std::find(trees[i].begin(), trees[i].end(), u) != trees[i].end())
            {
                uindex = i;
            }
            if (std::find(trees[i].begin(), trees[i].end(), v) != trees[i].end())
            {
                vindex = i;
            }
        }
    
        if (uindex != vindex)
        {
            trees[uindex].splice(trees[uindex].end(), trees[vindex]);
            return true;
        }
    
        return false;
    }
    
    void kruskal(const int (*g)[VERTEX])
    {
        std::vector<stEdge> edges;
        initEdges(edges, g);
    
        std::vector<std::list<int> > trees(VERTEX);
        for (int i = 0; i < VERTEX; ++i)
        {
            trees[i].push_back(i);
        }
    
        for (auto e : edges)
        {
            if (notSameTree(e.u, e.v, trees))
            {
                std::cout << szVertex[e.u] << "---" << szVertex[e.v] << std::endl;
            }
        }
    }
    
    int main()
    {
        int g[VERTEX][VERTEX] = {0};
    
        createGraph(g);
    
        kruskal(g);
    
        return 0;
    }

    prim算法:

    #include <iostream>
    #include <list>
    #include <vector>
    #include <algorithm>
    
    const int   INFINITE  = 0x7FFFFFFF;
    const int   VERTEX    = 6;
    const char  szVertex[] = { 'A', 'B', 'C', 'D', 'E', 'F' };
    
    
    struct stEdge
    {
        int index;
        int weight;
    };
    
    void createGraph(int (*g)[VERTEX])
    {
        for (int i = 0; i < VERTEX; i++)
        {
            for (int j = 0; j < VERTEX; j++)
            {
                g[i][j] = INFINITE;
            }
        }
        g[0][1] = 6; g[0][2] = 1; g[0][3] = 5;
        g[1][0] = 6; g[1][2] = 5; g[1][4] = 3;
        g[2][0] = 1; g[2][1] = 5; g[2][3] = 5; g[2][4] = 6; g[2][5] = 4;
        g[3][0] = 5; g[3][2] = 5; g[3][5] = 2;
        g[4][1] = 3; g[4][2] = 6; g[4][5] = 6;
        g[5][2] = 4; g[5][3] = 2; g[5][4] = 6;
    }
    
    int minIndex(const stEdge *weightArr, int len)
    {
        int min = INFINITE;
        int idx = -1;
    
        for (int i = 0; i < len; ++i)
        {
            if (weightArr[i].weight != 0 && min > weightArr[i].weight)
            {
                min = weightArr[i].weight;
                idx = i;
            }
        }
    
        return idx;
    }
    
    void prim(const int (*g)[VERTEX], int index)
    {
        stEdge weightArr[VERTEX];
    
        weightArr[index].weight = 0;
        weightArr[index].index = index;
        for (int i = 0; i < VERTEX; ++i)
        {
            if (i != index)
            {
                weightArr[i].index = index;
                weightArr[i].weight = g[index][i];
            }
        }
    
        for (int i = 1; i < VERTEX; ++i)
        {
            int nextIndex = minIndex(weightArr, VERTEX);
            if (nextIndex != -1)
            {
                std::cout << szVertex[weightArr[nextIndex].index] << "---" << szVertex[nextIndex] << std::endl;
    
                weightArr[nextIndex].weight = 0;
                weightArr[nextIndex].index = nextIndex;
                for (int j = 0; j < VERTEX; ++j)
                {
                    if (weightArr[j].weight != 0 && g[nextIndex][j] < weightArr[j].weight)
                    {
                        weightArr[j].index = nextIndex;
                        weightArr[j].weight = g[nextIndex][j];
                    }
                }
            }
        }
    }
    
    int main()
    {
        int g[VERTEX][VERTEX] = {0};
    
        createGraph(g);
    
        prim(g, 0);
    
        return 0;
    }

    转载自:https://blog.csdn.net/luoshixian099/article/details/51908175

  • 相关阅读:
    python简介
    计算机基础
    C# 验证数字
    在字符串指定的索引下添加字符,输出换行
    js中实现子页面向父页面中赋值
    js搜索相同类型的控件全选、取值(Checkbox)
    Nhibernate中多Or条件的查询,很多Or的查询
    js遍历checkbox获取数据
    Jquery获取web窗体关闭事件,排除刷新页面
    两年多的工作感悟
  • 原文地址:https://www.cnblogs.com/zuofaqi/p/9966540.html
Copyright © 2011-2022 走看看