zoukankan      html  css  js  c++  java
  • DS实验题 PlayGame Kruskal(UnionFindSet)

    题目:

    思路:

    有两种做法,一种是Prim算法,另外一种则是我所使用的Kruskal算法,Kruskal的算法实现可以参考:最小生成树-Prim算法和Kruskal算法,讲的已经是十分清楚了。

    具体算法实现:
    1.首先用结构体数组存储输入的边,并且初始化一个并查集思想中的父亲数组fa[i];

    2.用sort根据边权进行排序,边权小的边在前,大的在后;

    3.从1到m遍历已经排好序的边

    (1)遍历到边i,其两个节点分别是a和b,查找两个节点的祖先A和B
    (2)如果A == B,加入边i会形成环路,则跳过该边,continue。
    (3)如果A != B,进行祖先之间的Union:执行 fa[A] = B 或者 fa[B] = A,之后进行计数器的自增以及最小生成树长度的记录。

    4.当加入的边为n-1条时(通过计数器反映),结束循环。

    其中非常需要注意的一点是,并查集的合并,指的是祖先之间的合并。

    代码

    //
    //  main.cpp
    //  Kruskal
    //
    //  Created by wasdns on 16/12/22.
    //  Copyright © 2016年 wasdns. All rights reserved.
    //
    
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    struct stedge
    {
        int u, v, len;
    };
    
    bool cmp(stedge s1, stedge s2)
    {
        return s1.len < s2.len;
    }
    
    stedge seg[100000];
    
    int fa[100005];
    
    void Inifa(int n)
    {
        for (int i = 1; i <= n; i++)
        {
            fa[i] = i;
        }
    }
    
    int findfa(int x)
    {
        int f = x;
        
        while (f != fa[f])
        {
            f = fa[f];
        }
        
        int i = x, j;
        
        while (i != f)
        {
            j = fa[i];
            
            fa[i] = f;
            
            i = j;
        }
        
        return f;
    }
    
    int main()
    {
        int i, n, m;
        
        cin >> n >> m;
        
        Inifa(n);
        
        int u, v, w;
        
        for (i = 1; i <= m; i++)
        {
            cin >> u >> v >> w;
            
            seg[i].u = u;
            seg[i].v = v;
            seg[i].len = w;
        }
        
        sort(seg+1, seg+m+1, cmp);
        
        int cnt = 0, lencnt = 0;
        
        for (i = 1; i <= m; i++)
        {
            int fa1 = findfa(seg[i].u);
            int fa2 = findfa(seg[i].v);
            
            if (fa1 == fa2) continue;
            
            cnt++;
            
            lencnt += seg[i].len;
            
            fa[fa1] = fa2;         //一定是祖先找祖先合并
            
            if (cnt == n-1) break;
        }
        
        cout << lencnt;
        
        return 0;
    }
    
    /*
     4
     6
     1 2 1
     2 3 2
     1 3 3
     2 4 3
     3 4 5
     1 4 4
     */
    
    

    2016/12/22

  • 相关阅读:
    配置.net 3.0开发环境
    SQL分页语句
    SQL注入的实现原理和防范
    asp.net页面缓存技术
    内网渗透基础
    内网渗透工作组信息收集
    ORA00702: bootstrap verison ” inconsistent with version ’8.0.0.0.0′
    我的新blog
    专业Oracle数据库恢复技术支持
    高等代数第2讲——n元线性方程组解的情况
  • 原文地址:https://www.cnblogs.com/qq952693358/p/6211691.html
Copyright © 2011-2022 走看看