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

    最小生成树有两种算法:Kruskal算法 和 Prim算法

    算法一:Kruskal算法

    基本思想就是:每次选择目前剩余的边中的权值最小的边,若将此边加入图中,不会形成环,则可以加入图中,否则舍弃。判断是否会形成环可以使用并查集算法。

    以 HDU - 1879 题为例(题目链接:https://vjudge.net/problem/HDU-1879 ),代码如下:

     1 #include <algorithm>
     2 #include <queue>
     3 #include <cstdio>
     4 #include <iostream>
     5 #include <cstring>
     6 #include <map>
     7 #include <cmath>
     8 using namespace std;
     9 
    10 const int maxn = 100 + 10;
    11 int N, M;
    12 
    13 int ans, f[maxn];
    14 
    15 struct Node{
    16     int x, y, d;
    17     Node(int x=0,int y=0,int d=0):x(x),y(y),d(d){}
    18     bool operator < (const Node& t) const {
    19         return d < t.d;
    20     }
    21 };
    22 Node edge[maxn*maxn];
    23 
    24 // 并查集
    25 int find(int a) {
    26     return f[a] == a ? a : f[a]=find(f[a]);
    27 }
    28 
    29 void Kruskal(){
    30     for(int i = 1; i <= N; ++i) f[i] = i;
    31 
    32     //按照边的权值从小到大进行选取
    33     for(int i = 0; i < M; ++i){
    34         int u = find(edge[i].x);
    35         int v = find(edge[i].y);
    36         if(u != v){
    37             f[u] = v;
    38             ans += edge[i].d;
    39         }
    40     }
    41 }
    42 
    43 int main(){
    44     while(scanf("%d", &N) == 1 && N){
    45         M = N*(N-1)/2;
    46         for(int i = 0; i < M; ++i){
    47             int u, v;
    48             scanf("%d%d%d%d", &edge[i].x, &edge[i].y, &u, &v);
    49             if(v == 1) edge[i].d = 0;
    50             else edge[i].d = u;
    51         }
    52         sort(edge, edge+M);
    53         ans = 0;
    54         Kruskal();
    55         cout << ans << endl;
    56     }
    57     return 0;
    58 }
    View Code

    这个算法是按照边来计算的,所以算法复杂度为O(eloge),下面的Prim算法是依据结点来计算的,复杂度是O(n^2)

    算法二:Prim算法

    基本思想和Dijkstra算法思想有点类似,可以参考Dijkstra算法的思想,链接:https://www.cnblogs.com/DynastySun/p/9351584.html,代码如下:

     1 #include <algorithm>
     2 #include <queue>
     3 #include <cstdio>
     4 #include <iostream>
     5 #include <cstring>
     6 #include <map>
     7 #include <cmath>
     8 using namespace std;
     9 
    10 const int INF = 0x3f3f3f3f;
    11 const int maxn = 100 + 10;
    12 
    13 int ans, N, M, G[maxn][maxn];
    14 
    15 void Prim(){
    16     int start = 1;
    17     int flag[maxn], dis[maxn];
    18     memset(flag, 0, sizeof(flag));
    19     for(int i = 1; i <= N; ++i) {
    20         dis[i] = G[i][1];
    21         last[i] = start;
    22     }
    23     dis[start] = 0;
    24     flag[start] = 1;
    25     for(int i = 1; i < N; ++i){
    26         int MIN = INF;
    27         int k;
    28         for(int j = 1; j <= N; ++j)
    29             if(!flag[j] && MIN > dis[j]){
    30                 MIN = dis[j];
    31                 k = j;
    32             }
    33 
    34         flag[k] = 1;
    35         ans += MIN;
    36 
    37         for(int j = 1; j <= N; ++j)
    38             if(!flag[j] && dis[j] > G[j][k]) {
    39                 dis[j] = G[k][j];
    40             }
    41     }
    42 }
    43 
    44 int main(){
    45     while(scanf("%d", &N) == 1 && N){
    46         memset(G, INF, sizeof(G));
    47         M = N*(N-1)/2;
    48         for(int i = 0; i < M; ++i){
    49             int a, b, c, d;
    50             scanf("%d%d%d%d", &a, &b, &c, &d);
    51             if(d == 1) G[a][b] = G[b][a] = 0;
    52             else G[a][b] = G[b][a] = c;
    53         }
    54         ans = 0;
    55         Prim();
    56         printf("%d
    ", ans);
    57     }
    58     return 0;
    59 }
    View Code
  • 相关阅读:
    用SSMS连接Azure Sql Database 与连接本地库的一些操作区别
    python_高级进阶(3)线程
    python_高级进阶(2)进程与并发
    python_高级进阶(1)进程与并发
    python网络(2)_Udp协议
    python网络(2)_Tcp协议
    python网络(1)_认知
    python异常处理
    python面向对象(5)__特殊双下方法
    python面向对象(4)_细分类的组成成员
  • 原文地址:https://www.cnblogs.com/DynastySun/p/9360077.html
Copyright © 2011-2022 走看看