zoukankan      html  css  js  c++  java
  • 最小生成树(大纲,待补全)

    最小生成树

    最小生成树 - OI Wiki

    前置知识

    生成树

    最小生成树

    Prim

    不常用(又不如kruskal快又不如kruskal好写),了解即可

    思路类似dijkstra

    以下为我也不知道我啥时候写出来的代码

    邻接矩阵版本

    #include <bits/stdc++.h>
    using namespace std;
    int n, m;
    int t[5001][5001];
    int d[5001];
    bool vis[5001];
    int ans, cnt;
    int main()
    {
        cin >> n >> m;
        for (int i = 1; i <= n; i++)
        {
            for (int j = 1; j <= n; j++)
                t[i][j] = 1000000005;
            t[i][i] = 0;
        }
        for (int i = 1; i <= m; i++)
        {
            int u, v, w;
            cin >> u >> v >> w;
            t[v][u] = t[u][v] = min(t[u][v], w);
        }
        for (int i = 1; i <= n; i++)
        {
            d[i] = 1000000005;
        }
        for (int i = 1; i <= n; i++)
        {
            d[i] = t[1][i];
        }
        d[1] = 0;
        vis[1] = 1;
        while (cnt <= n - 1)
        {
            int mini = 0, mind = 1000000005;
            for (int i = 1; i <= n; i++)
            {
                if (!vis[i] && d[i] < mind)
                {
                    mind = d[i];
                    mini = i;
                }
            }
            if (mini == 0)
            {
                break;
            }
            cnt++;
            ans += mind;
            d[mini] = 0;
            vis[mini] = 1;
            for (int i = 1; i <= n; i++)
            {
                d[i] = min(d[i], t[mini][i]);
            }
        }
        if (cnt == n - 1)
        {
            cout << ans << endl;
        }
        else
        {
            cout << -1 << endl;
        }
    }
    

    邻接表版本

    #include <bits/stdc++.h>
    using namespace std;
    int n, m;
    int fir[200001], to[1000001], nxt[1000001], dis[1000001], ecnt;
    void add(int u, int v, int w)
    {
        to[++ecnt] = v;
        dis[ecnt] = w;
        nxt[ecnt] = fir[u];
        fir[u] = ecnt;
    }
    int d[200001];
    bool vis[200001];
    int cnt;
    long long ans;
    struct node
    {
        int x, d;
        node(int x, int d) : x(x), d(d) {}
    };
    bool operator<(node a, node b)
    {
        return a.d > b.d;
    }
    priority_queue<node> q;
    int main()
    {
        cin >> n >> m;
        for (int i = 1; i <= m; i++)
        {
            int u, v, w;
            cin >> u >> v >> w;
            add(u, v, w);
            add(v, u, w);
        }
        for (int i = 1; i <= n; i++)
            d[i] = 1000000005;
        q.push(node(1, 0));
        d[1] = 0;
        cnt = -1;
        while (!q.empty() && cnt < n - 1)
        {
            node h = q.top();
            q.pop();
            if (vis[h.x])
                continue;
            vis[h.x] = 1;
            d[h.x] = 0;
            cnt++;
            ans += h.d;
            for (int e = fir[h.x]; e; e = nxt[e])
            {
                if (d[to[e]] > dis[e])
                {
                    d[to[e]] = dis[e];
                    q.push(node(to[e], d[to[e]]));
                }
            }
        }
        if (cnt == n - 1)
        {
            cout << ans << endl;
        }
        else
        {
            cout << "orz" << endl;
        }
    }
    

    Kruskal

    思想:贪心

    每次找一条最短的边往生成树里加

    正确性

    Kruskal 证明 - OI Wiki

    待补充

    代码

    #include<bits/stdc++.h>
    using namespace std;
    struct edge{
        int from,to,dis;
    }g[500001];
    bool cmp(edge a,edge b){
        return a.dis<b.dis;
    }
    int fa[200001];
    int getf(int x){
        if(fa[x]==x)return x;
        fa[x]=getf(fa[x]);
        return fa[x];
    }
    int n,m,cnt;
    long long ans;
    int main(){
        cin>>n>>m;
        for(int i=1;i<=m;i++){
            cin>>g[i].from>>g[i].to>>g[i].dis;
        }
        for(int i=1;i<=n;i++){
            fa[i]=i;
        }
        sort(g+1,g+m+1,cmp);
        for(int i=1;i<=m&&cnt<n-1;i++){
            int fu=getf(g[i].from),fv=getf(g[i].to);
            if(fu==fv)continue;
            fa[fu]=fv;
            cnt++;
            ans+=g[i].dis;
        }
        if(cnt==n-1){
            cout<<ans<<endl;
        }else{
            cout<<"orz";
        }
    }
    

    讲到的题

    U69308 【常数PK系列】 #3 最小生成树

    P1550 [USACO08OCT]Watering Hole G

    P1536 村村通

    P1396 营救

    [P2820 局域网](https://www.luogu.com.cn/problem/P2820

  • 相关阅读:
    k8s 权限控制初探
    golang gRPC 入门
    gpushare-scheduler-extender 升级依赖引发关于 golang dep 工具的思考
    admission webhook 初探(编译篇)
    以 gpushare-device-plugin 为例,探究 Resource yaml 配置
    编译 gpushare-device-plugin
    浅谈 docker 挂载 GPU 原理
    CCF计算机职业资格认证考试题解
    优达学城机器学习工程师纳米学位项目介绍
    IEEEXtreme 极限编程大赛题解
  • 原文地址:https://www.cnblogs.com/water-lift/p/12678307.html
Copyright © 2011-2022 走看看