zoukankan      html  css  js  c++  java
  • 最小生成树

    最小生成树的算法分为 prim和kruscal算法

    初始状态:

    设置2个数据结构:

    lowcost[i]:表示以i为终点的边的最小权值,当lowcost[i]=0说明以i为终点的边的最小权值=0,也就是表示i点加入了MST

    mst[i]:表示对应lowcost[i]的起点,即说明边<mst[i],i>是MST的一条边,当mst[i]=0表示起点i加入MST

    我们假设V1是起始点,进行初始化(*代表无限大,即无通路):

    lowcost[2]=6,lowcost[3]=1,lowcost[4]=5,lowcost[5]=*,lowcost[6]=*

    mst[2]=1,mst[3]=1,mst[4]=1,mst[5]=1,mst[6]=1,(所有点默认起点是V1)

    明显看出,以V3为终点的边的权值最小=1,所以边<mst[3],3>=1加入MST

     

    此时,因为点V3的加入,需要更新lowcost数组和mst数组:

    lowcost[2]=5,lowcost[3]=0,lowcost[4]=5,lowcost[5]=6,lowcost[6]=4

    mst[2]=3,mst[3]=0,mst[4]=1,mst[5]=3,mst[6]=3


    明显看出,以V6为终点的边的权值最小=4,所以边<mst[6],6>=4加入MST


    此时,因为点V6的加入,需要更新lowcost数组和mst数组:

    lowcost[2]=5,lowcost[3]=0,lowcost[4]=2,lowcost[5]=6,lowcost[6]=0

    mst[2]=3,mst[3]=0,mst[4]=6,mst[5]=3,mst[6]=0


    明显看出,以V4为终点的边的权值最小=2,所以边<mst[4],4>=4加入MST

     


    此时,因为点V4的加入,需要更新lowcost数组和mst数组:

    lowcost[2]=5,lowcost[3]=0,lowcost[4]=0,lowcost[5]=6,lowcost[6]=0

    mst[2]=3,mst[3]=0,mst[4]=0,mst[5]=3,mst[6]=0


    明显看出,以V2为终点的边的权值最小=5,所以边<mst[2],2>=5加入MST


    此时,因为点V2的加入,需要更新lowcost数组和mst数组:

    lowcost[2]=0,lowcost[3]=0,lowcost[4]=0,lowcost[5]=3,lowcost[6]=0

    mst[2]=0,mst[3]=0,mst[4]=0,mst[5]=2,mst[6]=0


    很明显,以V5为终点的边的权值最小=3,所以边<mst[5],5>=3加入MST


    lowcost[2]=0,lowcost[3]=0,lowcost[4]=0,lowcost[5]=0,lowcost[6]=0

    mst[2]=0,mst[3]=0,mst[4]=0,mst[5]=0,mst[6]=0


    至此,MST构建成功,如图所示:

     1 #include <iostream>
     2 
     3 using namespace std;
     4 
     5 #define MAX 100
     6 #define MAXCOST 0xfffffff
     7 
     8 int graph[MAX][MAX];
     9 int lowcost[MAX];
    10 int mst[MAX];
    11 int n,sum = 0;
    12 
    13 int prim()
    14 {
    15     int min,minid;
    16     for (int i=2;i<=n;i++)
    17     {
    18         lowcost[i] = graph[1][i];
    19         mst[i] = 1;
    20     }
    21     mst[1] = 0;
    22     for (int i=2;i<=n;i++)
    23     {
    24         min = MAXCOST;
    25         minid = 0;
    26         for (int j=2;j<=n;j++)
    27         {
    28             if (lowcost[j] < min && lowcost[j]!=0)
    29             {
    30                 min = lowcost[j];
    31                 minid = j;
    32             }
    33         }
    34         sum += min;
    35         lowcost[minid] = 0;
    36         for (int j=2;j<=n;j++)
    37         {
    38             if (graph[minid][j] < lowcost[j])
    39             {
    40                 lowcost[j] = graph[minid][j];
    41                 mst[j] = minid;
    42             }
    43         }
    44     }
    45     return sum;
    46 }
    47 
    48 int main()
    49 {
    50     int m;
    51     cin >> n >> m;    // n代表图的顶点,m代表图的边
    52     //初始化图
    53     for (int i=1;i<=n;i++)
    54     {
    55         for (int j=1;j<=n;j++)
    56         {
    57             graph[i][j] = MAXCOST;
    58         }
    59     }
    60     //构造图
    61     for (int k=1;k<=m;k++)
    62     {
    63         int i,j,cost;
    64         cin >> i >> j >> cost;
    65         graph[i][j] = graph[j][i] = cost;
    66     }
    67     cout << prim() << endl;
    68     return 0;
    69 }
    View Code

    kruscal算法 是使用了并查集。始终选择当前可用的最小边权的边(可以直接快排或者algorithm的sort)。每次选择边权最小的边链接两个端点是kruskal的规则,并实时判断两个点之间有没有间接联通。

    同样的,模拟过程

    对权值进行排序,随后选取最小对权值的边。

    排序后,最小的边自然是第8条边,于是4和6相连

    遍历继续,第二小的边是1号,1和2联通。

    再继续

    继续

    其次是dis为15的边4,但是2和4已经相连了,pass。

    然后是dis为16的两条边(边2和边9),边2连接1和3,边9连接3和6,它们都已经间接相连,pass。

    再然后就是dis为22的边10,它连接5和6,5还没有加入组织,所以使用这边。继续,发现此时已经连接了n-1条边,结束,最后图示如下:

    魏队的板子:

     1 #include <math.h>
     2 #include <stdio.h>
     3 #include <stdlib.h>
     4 #include <iostream>
     5 #include <algorithm>
     6 #include <string>
     7 #include <string.h>
     8 #include <vector>
     9 #include <map>
    10 #include <stack>
    11 #include <set>
    12 #include <queue>
    13 
    14 
    15 #define LL long long
    16 #define INF 0x3f3f3f3f
    17 #define ls nod<<1
    18 #define rs (nod<<1)+1
    19 const int maxn = 2e5+7;
    20 const double eps = 1e-9;
    21 
    22 int n,m,ans,cnt,fa[5050];
    23 
    24 struct node{
    25     int u, v, w;
    26 }e[maxn];
    27 
    28 bool cmp(node a, node b)
    29 {
    30     return a.w < b.w;
    31 }
    32 
    33 int fid(int x)
    34 {
    35     return x == fa[x] ? x : fid(fa[x]);
    36 }
    37 
    38 bool unite(int r1, int r2)///冰茶鸡
    39 {
    40     int fidroot1 = fid(r1), fidroot2 = fid(r2);
    41     if(fidroot1 != fidroot2) {
    42         fa[fidroot2] = fidroot1;
    43         return true;
    44     }
    45     return false;
    46 }
    47 
    48 
    49 void init(int n)
    50 {
    51     for(int i = 1; i <= n; i++) {
    52         fa[i] = i;
    53     }
    54     ans = 0;
    55     cnt = 0;
    56 }
    57 
    58 void kruskal()
    59 {
    60     std::sort(e+1, e+m+1, cmp);
    61     for(int i = 1; i <= m; i++) {
    62         int eu = fid(e[i].u);
    63         int ev = fid(e[i].v);
    64         if(eu == ev) {
    65             continue;
    66         }
    67         ans += e[i].w;
    68         fa[ev] = eu;
    69         if(++cnt == n-1) {
    70             break;
    71         }
    72     }
    73 }
  • 相关阅读:
    大写的服,看完这篇你还不懂RocketMQ算我输
    写一个通用的幂等组件,我觉得很有必要
    如何将分布式锁封装的更优雅
    哇,ElasticSearch多字段权重排序居然可以这么玩
    每日一道 LeetCode (52):三数之和
    JVM 第六篇:极致优化 IDEA 启动速度
    JVM 第五篇:命令行 JVM 故障处理工具
    JVM 第四篇:可视化 JVM 故障处理工具
    JVM 第三篇:Java 类加载机制
    JVM 第二篇:垃圾收集器以及算法
  • 原文地址:https://www.cnblogs.com/-Ackerman/p/10822909.html
Copyright © 2011-2022 走看看