• BZOJ1232: [Usaco2008Nov]安慰奶牛cheer(最小生成树)


    题意:给一个图 需要找到一个子图使得所有点都连通

       然后再选择一个点做为起点 走到每个点并回到起点

       每条边,每个点被经过一次就要花费一次边权、点权

    题解:肯定是找一颗最小生成树嘛

       然后惊奇的发现 任意选一个点做为一个起点遍历的答案都是 每条边走两次

       每个点度数是多少点权就统计几次 依题意起点多统计一次 那么起点就选一个点权最小的点

       然后把每条边两个端点的点权赋给它 跑一个最小生成树

       还是挺有意思的

    #include <bits/stdc++.h>
    using namespace std;
    
    int val[10005];
    int vis[10005];
    int pre[10005];
    struct node
    {
        int u, v, w;
    }E[200005];
    
    bool cmp(node A, node B) {return A.w < B.w;}
    
    int find(int x)
    {
        if(x == pre[x]) return x;
        else return pre[x] = find(pre[x]);
    }
    
    int main()
    {
        int cnt = 0;
        int n, p;
        scanf("%d%d", &n, &p);
    
        for(int i = 1; i <= n; i++) pre[i] = i;
        int ans = 0;
        int tmp = 1005;
        for(int i = 1; i <= n; i++) scanf("%d", &val[i]), tmp = min(tmp, val[i]);
        ans += tmp;
    
        for(int i = 1; i <= p; i++)
        {
            int a, b, c; scanf("%d%d%d", &a, &b, &c);
            E[++cnt].u = a; E[cnt].v = b; E[cnt].w = c * 2 + val[a] + val[b];
        }
        sort(E + 1, E + 1 + cnt, cmp);
    
        int tot = 0;
        for(int i = 1; i <= cnt; i++)
        {
            if(tot == n - 1) break;
            int ax = find(E[i].u);
            int bx = find(E[i].v);
            if(ax == bx) continue;
    
            tot++;
            ans += E[i].w;
            pre[ax] = bx;
        }
        printf("%d
    ", ans);
        return 0;
    }
    View Code
  • 相关阅读:
    c语言数据处理!
    指针的概念
    return的用处
    用java写随机出题
    java 新手
    分支程序设计。
    不同车型 不同起步价不同费用的问题(switch语句)
    这两天做了很多随机函数的用法(下面是一个出题实验)。
    yum 命令讲解
    日常工作中一些常用命令
  • 原文地址:https://www.cnblogs.com/lwqq3/p/9833071.html
Copyright © 2020-2023  润新知