zoukankan      html  css  js  c++  java
  • hihocoder 1109 堆优化的Prim算法

      题目链接:http://hihocoder.com/problemset/problem/1109 , 最小生成树 + 堆优化(优先队列)。

      可以用优先队列,也可以自己手动模拟堆,为了练手,我两种都试了下,优先队列还是要方便一点,不过堆要快一点。

      没有无缘无故的爱,也没有无缘无故减少的时间复杂度。所以,好好学算法。

     


    堆优化的代码:

    #include <iostream>
    #include <cstdio>
    #include <vector>
    #include <queue>
    #include <cmath>
    #include <string>
    #include <string.h>
    #include <algorithm>
    using namespace std;
    #define LL __int64
    #define eps 1e-8
    #define INF 1e8
    #define lson l , m , rt << 1
    #define rson m + 1 , r , rt << 1 | 1
    const int MOD = 2333333; 
    const int maxn = 100000 + 5;
    struct Edge {    //邻接表表示图
        int v , w;
        bool operator < (const Edge &tmp) const {
            return w < tmp.w;
        }
    } a[maxn];
    vector <Edge> e[maxn];
    int vis[maxn] , dist[maxn];
    
    void PushUp(int rt , int r)
    {        //自下向上更新以rt为根,r为右边界的堆
        int i = r >> 1;
        while(i >= rt) {
            if(a[r] < a[i]) {
                swap(a[r] , a[i]);
                r = i;
                i >>= 1;
            } else {
                break;
            }
        }
    }
    void PushDown(int rt , int r)
    {        //自上向下更新以rt为根,r为右边界的堆
        int i = rt << 1;
        while(i <= r) {
            if(a[i].w > a[i + 1].w)
                i++;
            if(a[i] < a[rt]) {
                swap(a[i] , a[rt]);
                rt = i;
                i <<= 1;
            } else {
                break;
            }
        }
    }
    int Prim(int s , int n)
    {
        int tot , ans;    //tot表示堆中元素的个数
        tot = ans = 0;
        memset(vis , 0 , sizeof(vis));
        for(int i = 1 ; i <= n ; i++) 
            dist[i] = INF;
        a[++tot].v = s;
        a[tot].w = 0;
        while(tot >= 1) {
            Edge u = a[1];
            swap(a[1] , a[tot]);
            a[tot--].w = INF;
            PushDown(1 , tot);  
            if(vis[u.v])
                continue;
            ans += u.w;
            vis[u.v] = 1;
            for(int i = 0 ; i < e[u.v].size() ; i++) {
                int j = e[u.v][i].v;
                if(dist[j] > e[u.v][i].w) {
                    dist[j] = e[u.v][i].w;
                    if(!vis[j]) {
                        a[++tot] = e[u.v][i];
                        PushUp(1 , tot);
                    }
                }
            }
        }
        return ans;
    }
    int main()
    {
        int n , m , u , v , w;
        scanf("%d %d" , &n , &m);
        while(m--) {
            scanf("%d %d %d" , &u , &v , &w);
            Edge tmp = {v , w};
            e[u].push_back(tmp);
            tmp.v = u;
            e[v].push_back(tmp);
        }
        printf("%d
    " , Prim(1 , n));
        return 0;
    }

    优先队列优化(注意重载运算符地方的细节):

    #include <iostream>
    #include <cstdio>
    #include <vector>
    #include <queue>
    #include <cmath>
    #include <string>
    #include <string.h>
    #include <algorithm>
    using namespace std;
    #define LL __int64
    #define eps 1e-8
    #define INF 1e8
    #define lson l , m , rt << 1
    #define rson m + 1 , r , rt << 1 | 1
    const int MOD = 2333333; 
    const int maxn = 100000 + 5;
    struct Edge {
        int v , w;
        bool operator < (const Edge &tmp) const {
            return w > tmp.w;
        }
    } a[maxn];
    vector <Edge> e[maxn];
    int vis[maxn] , dist[maxn];
    
    int Prim(Edge s , int n)
    {
        priority_queue <Edge> que;
        int ans = 0;
        for(int i = 1 ; i <= n ; i++) {
            dist[i] = INF;
            vis[i] = 0;
        }
        que.push(s);
        while(!que.empty()) {
            Edge u = que.top();
            que.pop();
            if(vis[u.v])
                continue;
            vis[u.v] = 1;
            ans += u.w;
            for(int i = 0 ; i < e[u.v].size() ; i++) {
                int j = e[u.v][i].v;
                if(dist[j] > e[u.v][i].w && !vis[j]) {
                    dist[j] = e[u.v][i].w;
                    que.push(e[u.v][i]);
                }
            }
        }
        return ans;
    }
    int main()
    {
        int n , m , u , v , w;
        scanf("%d %d" , &n , &m);
        while(m--) {
            scanf("%d %d %d" , &u , &v , &w);
            Edge tmp = {v , w};
            e[u].push_back(tmp);
            tmp.v = u;
            e[v].push_back(tmp);
        }
        Edge tmp = {1 , 0};
        printf("%d
    " , Prim(tmp , n));
        return 0;
    }
  • 相关阅读:
    Python Django :HTTP生命周期
    Docker简介及Centos 7 安装[初步配置]
    python:Django 简介。
    python :Django url /views /Template 文件介绍
    python:异常处理及程序调试
    python之正则表达式【re】
    Day 21 python :面向对象 类的相关内置函数 /单例模式 /描述符
    Day 22: 软件开发目录设计规范
    Day 20: 面向对象【多态,封装,反射】字符串模块导入/内置attr /包装 /授权
    SpringCloud教程 | 第九篇: 服务链路追踪(Spring Cloud Sleuth)
  • 原文地址:https://www.cnblogs.com/H-Vking/p/4317009.html
Copyright © 2011-2022 走看看