zoukankan      html  css  js  c++  java
  • 新的开始-(最小生成树)

    咕咕咕

    (努力让自己的题解变成认真的题解,但还是忍不住要吐槽,一本通里题目名字为什么都这么中二)

    一开始,觉得就是一个最小生成树的裸题。

    于是就没想太多,直接,在点权值中取最小值,再直接求最小生成树,求和。

    结果凄惨的只拿了50,de了半天bug,甚至怀疑过自己是不是kruskal的板子写错了

    还是看了别人的正解,才发现自己思路有漏洞

    应该建一个虚拟源点,每个点i连向虚拟源点的边权为发电站费用v[ i ]

    为什么呢..?因为虽然是双向边,但存边的时候只能单向存。

    这就导致,从哪个点出发,会决定了,有的边加不加的进去。

    于是...不能简简单单的取出发电站费用中最少的.

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    
    inline int read()
    {
        int sum = 0,p = 1;
        char ch = getchar();
        while(ch < '0' || ch > '9')
        {
            if(ch == '-')
                p = -1;
            ch = getchar();
        }
        while(ch >= '0' && ch <= '9')
        {
            (sum *= 10) += ch - '0';
            ch = getchar();
        } 
        return sum * p;
    }
    
    const int N = 310; 
    int n,ans,tot,cnt;
    struct edge
    {
        int frm,to,wei;
    }e[N * N];
    int fa[N];
    
    int findfa(int x)
    {
        return fa[x] == x ? x : findfa(fa[x]);
    }
    
    bool cmp(edge a,edge b)
    {
        return a.wei < b.wei;
    }
    
    void kruskal()
    {
        sort(e+1,e+cnt+1,cmp);
        for(int i = 0;i <= n;i++)
            fa[i] = i;
        for(int i = 1;i <= cnt;i++)
        {
            int u = findfa(e[i].frm);
            int v = findfa(e[i].to);
            if(u == v)
                continue;
            fa[u] = v;
            ans += e[i].wei;
            if(++tot == n)
                break;
        }
    }
    
    int main()
    {
        n = read();
        int a;
        for(int i = 1;i <= n;i++)
        {
            a = read();
            e[++cnt].frm = 0;
            e[cnt].to = i;
            e[cnt].wei = a;
        }
        for(int i = 1;i <= n;i++)
            for(int j = 1;j <= n;j++)
            {
                a = read();
                if(i == j)
                    continue;
                e[++cnt].frm = i;
                e[cnt].to = j;
                e[cnt].wei = a;
            }
        kruskal();
        printf("%d",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    [TJOI2018]教科书般的亵渎
    luogu P4781 【模板】拉格朗日插值
    [SDOI2010]捉迷藏
    [CQOI2016]K远点对
    BZOJ4066 简单题
    [国家集训队]JZPFAR
    Understanding User and Kernel Mode
    Linux下如何查看系统启动时间和运行时间以及安装时间
    CentOS Linux搭建独立SVN Server全套流程(修改svn仓库地址、服务启动等)
    linux下获取占用CPU资源最多的10个进程,可以使用如下命令组合:
  • 原文地址:https://www.cnblogs.com/darlingroot/p/11279242.html
Copyright © 2011-2022 走看看