• 最小生成树 prim & kruskal


    给定一个无向图,如果他的某个子图中,任意两个顶点都能互相连通并且是一棵树,那么这棵树就叫做生成树(spanning tree).
    如果边上有权值,那么使得边权和最小的生成树叫做最小生成树(MST,Minimum Spanning Tree)


    1. prim算法:
      使用临界矩阵存储边,适用于两点之间只有一条边,或只需要保存最短或最长的一条边的情况。
      通过“加点”搜索最短路径;

    附代码,这里假设为无向图:
     1 #include<iostream>
     2 #include<cstring>
     3 using namespace std;
     4 
     5 #define INF 1e9
     6 const int N = 100+5;    //number of dots
     7 int n,m;
     8 int dis[N], vis[N], edge[N][N];
     9 
    10 void init()
    11 {
    12     memset(vis, 0, sizeof(0));
    13     vis[0]=1, dis[0]=0;     //start from 0
    14     
    15     for(int i=0; i<n; i++)
    16         for(int j=0; j<N; j++)
    17             edge[i][j]=INF;
    18 }
    19 
    20 int prim()
    21 {
    22     int mini, minx, count=0, cost=0;
    23     while(count<n) {
    24         mini = -1;
    25         minx = INF;
    26         for(int i=1; i<n; i++) {
    27             if(!vis[i] && dis[i]<minx) {
    28                 mini = i;
    29                 minx = dis[i];
    30             }
    31         }
    32         if(mini == -1) return -1;
    33         
    34         vis[mini] = 1;
    35         cost += minx;
    36         count++;
    37         
    38         for(int i=1; i<n; i++) {
    39             if(!vis[i] && edge[mini][i]<dis[i])
    40                 dis[i] = edge[mini][i];
    41         }
    42     }
    43     return cost;
    44 }
    45 
    46 int main()
    47 {
    48     cin>>n>>m;
    49     init();
    50     for(int a,b,v,i=0; i<m; i++) {
    51         cin>>a>>b>>v;
    52         edge[a][b] = edge[b][a] = v;    //undirected graph
    53     }
    54     
    55     prim();
    56     
    57     return 0;
    58 } 
    
    
    
    2. kruskal算法

      通过“加边”搜索最短路径;

      按照边的权值从小到大排序,再全部访问一遍,如果将该边加入当前生成树内不会产生环,那么就把这条边加入到生成树中,逐步扩大生成树的大小。

      接下来我们介绍如何判断是否产生重边。假设现在要把连接顶点u和顶点v的边e(u—>v,v—>u)加入到生成树中去,如果加入操作之前,u和v不在同一个连通分量内(两块不连接的图),那么加入e也不会产生圈。反之,如果u和v在同一个连通分量里,那么一定会产生圈。可以使用并查集判断是否属于同一个连通分量。

    
    
     1 #include<iostream>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 
     6 #define INF 1e9
     7 const int N = 100+5;    //number of dots
     8 const int M = 1000+5;
     9 int n,m;
    10 struct Edge {
    11     int from, to, value;
    12     bool operator<(const Edge &a) {
    13         return value<a.value;
    14     }
    15 }edge[M];
    16 int vis[N], f[N];
    17 
    18 int find(int x)
    19 {
    20     if(x != f[x])
    21         f[x] = find(f[x]);
    22     return f[x];
    23 }
    24 
    25 void init()
    26 {
    27     for(int i=0; i<n; i++)
    28         vis[i]=0, f[i] = i;
    29     sort(edge, edge+m);
    30 }
    31 
    32 int kruskal()
    33 {
    34     int cost=0;
    35     for(int i=0; i<m; i++) {
    36         int x = find(edge[i].from);
    37         int y = find(edge[i].to);
    38         if(x != y) {
    39             f[x] = y;
    40             cost += edge[i].value;
    41             vis[edge[i].from] = vis[edge[i].to] = 1;
    42         }
    43     }
    44 }
    45 
    46 int main()
    47 {
    48     cin>>n>>m;
    49     for(int i=0; i<m; i++)
    50         cin>>edge[i].from>>edge[i].to>>edge[i].value;
    51     
    52     init();
    53     kruskal();
    54     
    55     return 0;
    56 } 
    
    
    
     
  • 相关阅读:
    C++ 用libcurl库进行http通讯网络编程(转)
    树莓派声音设置
    在Linux终端命令行下播放音乐的命令(Ubuntu)
    2.1 LibCurl编程流程(转)
    linux编译curl库的动态库so(转)
    单片机中断的IE和IP寄存器(摘抄)
    MCS-51系列特殊功能寄存器(摘抄)
    linux c libcurl的简单使用(转)
    普林斯顿结构 VS 哈佛结构
    树莓派(raspberry pi)学习4: 更改键盘布局(转)
  • 原文地址:https://www.cnblogs.com/liubilan/p/9441269.html
Copyright © 2020-2023  润新知