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

    一直以来只会Kruskal

    prim和dijkstra很像

    只不过prim维护的是最短的边,而dijkstra维护的是最短的从起点到一个点的路径

    同时prim要注意当前拓展的边是没有拓展过的

    可以用堆优化

    #include<bits/stdc++.h>
    #define REP(i, a, b) for(register int i = (a); i < (b); i++)
    #define _for(i, a, b) for(register int i = (a); i <= (b); i++)
    using namespace std;
    
    const int MAXN = 5000 + 10;
    const int MAXM = 2e5 + 10;
    
    struct Edge{ int to, w, next; };
    Edge e[MAXM << 1];
    int head[MAXN], d[MAXN], vis[MAXN], n, m, tot;
    
    void AddEdge(int from, int to, int w)
    {
        e[tot] = Edge{to, w, head[from]};
        head[from] = tot++;
    }
    
    void read(int& x)
    {
        int f = 1; x = 0; char ch = getchar();
        while(!isdigit(ch)) { if(ch == '-') f = -1; ch = getchar(); }
        while(isdigit(ch)) { x = x * 10 + ch - '0'; ch = getchar(); }
        x *= f;
    }
    
    void prim()
    {
        vis[1] = 1;
        _for(i, 1, n) d[i] = i == 1 ? 0 : 1e9;
        for(int i = head[1]; ~i; i = e[i].next)
        {
            int v = e[i].to;
            d[v] = min(d[v], e[i].w);
        }
        
        int ans = 0;
        REP(k, 1, n)
        {
            int mint = 1e9, id;
            _for(i, 1, n)
                if(!vis[i] && d[i] < mint)
                {
                    mint = d[i];
                    id = i;
                }
            
            ans += mint;
            vis[id] = 1;
            
            for(int i = head[id]; ~i; i = e[i].next)
            {
                int v = e[i].to;
                if(vis[v]) continue;
                d[v] = min(d[v], e[i].w);
            }
        }
        printf("%d
    ", ans);
    }
    
    int main()
    {
        memset(head, -1, sizeof(head)); tot = 0;
        read(n); read(m);
        _for(i, 1, m)
        {
            int u, v, w;
            read(u); read(v); read(w);
            AddEdge(u, v, w);
            AddEdge(v, u, w);
        }
        prim();
        return 0;
    }

    堆优化版本

    #include<bits/stdc++.h>
    #define REP(i, a, b) for(register int i = (a); i < (b); i++)
    #define _for(i, a, b) for(register int i = (a); i <= (b); i++)
    using namespace std;
    
    const int MAXN = 5000 + 10;
    const int MAXM = 2e5 + 10;
    
    struct Edge{ int to, w, next; };
    Edge e[MAXM << 1];
    int head[MAXN], d[MAXN], vis[MAXN], n, m, tot;
    
    void AddEdge(int from, int to, int w)
    {
        e[tot] = Edge{to, w, head[from]};
        head[from] = tot++;
    }
    
    void read(int& x)
    {
        int f = 1; x = 0; char ch = getchar();
        while(!isdigit(ch)) { if(ch == '-') f = -1; ch = getchar(); }
        while(isdigit(ch)) { x = x * 10 + ch - '0'; ch = getchar(); }
        x *= f;
    }
    
    struct node
    {
        int id, w;
        bool operator < (const node& rhs) const
        {
            return w > rhs.w;
        }
    };
    priority_queue<node> q;
    
    void prim()
    {
        vis[1] = 1;
        _for(i, 1, n) d[i] = i == 1 ? 0 : 1e9;
        for(int i = head[1]; ~i; i = e[i].next)
        {
            int v = e[i].to;
            d[v] = min(d[v], e[i].w);
        }
        _for(i, 1, n) q.push(node{i, d[i]});
        
        int ans = 0;
        REP(k, 1, n)
        {
            int mint, id;
            while(1)
            {
                node x = q.top(); q.pop();
                if(vis[x.id]) continue;
                id = x.id, mint = x.w;
                break;
            }
    
            ans += mint;
            vis[id] = 1;
            
            for(int i = head[id]; ~i; i = e[i].next)
            {
                int v = e[i].to;
                if(vis[v]) continue;
                if(d[v] > e[i].w) 
                {
                    d[v] = e[i].w;
                    q.push(node{v, d[v]});
                }
            }
        }
        printf("%d
    ", ans);
    }
    
    int main()
    {
        memset(head, -1, sizeof(head)); tot = 0;
        read(n); read(m);
        _for(i, 1, m)
        {
            int u, v, w;
            read(u); read(v); read(w);
            AddEdge(u, v, w);
            AddEdge(v, u, w);
        }
        prim();
        return 0;
    }

     

  • 相关阅读:
    【测试】模拟一个全表扫描的sql,对其进行优化走索引,并且将执行计划稳定到baseLine。
    【练习】手工生成awr报告
    【测试】数据文件的删除恢复
    【练习】行迁移和行链接
    织梦栏目列表页第一个文章与其他文章不同样式
    织梦联动筛选【单选版】-支持手机站使用
    织梦联动枚举字段无二级时去掉多余下拉
    织梦联动类型地区联动三级修复以及省份-市级-地区分开+高亮
    织梦联动枚举字段添加一级分类如果超过132个自动变成二级修复教程
    织梦后台自定义表单联动地区显示为数字的真正解决方法
  • 原文地址:https://www.cnblogs.com/sugewud/p/9886395.html
Copyright © 2011-2022 走看看