• 安慰奶牛(最小生成树)


     1 问题描述
     2 Farmer John变得非常懒,他不想再继续维护供奶牛之间供通行的道路。道路被用来连接N个牧场,牧场被连续地编号为1到N。
    每一个牧场都是一个奶牛的家。FJ计划除去P条道路中尽可能多的道路,但是还要保持牧场之间 的连通性。
    你首先要决定那些道路是需要保留的N-1条道路。第j条双向道路连接了牧场Sj和Ej(1 <= Sj <= N; 1 <= Ej <= N; Sj != Ej),而且走完它需要Lj的时间。
    没有两个牧场是被一条以上的道路所连接。奶牛们非常伤心,因为她们的交通系统被削减了。你需要到每一个奶牛的住处去安慰她们。每次你到达第i个牧场的时候(即使你已经到过),
    你必须花去Ci的时间和奶牛交谈。你每个晚上都会在同一个牧场(这是供你选择的)过夜,直到奶牛们都从悲伤中缓过神来。在早上 起来和晚上回去睡觉的时候,你都需要和在你睡觉的牧场的奶牛交谈一次。
    这样你才能完成你的 交谈任务。假设Farmer John采纳了你的建议,请计算出使所有奶牛都被安慰的最少时间。
    3 4 输入格式 5 第1行包含两个整数N和P。 6 接下来N行,每行包含一个整数Ci。 7 接下来P行,每行包含三个整数Sj, Ej和Lj。 8 9 输出格式 10 输出一个整数, 所需要的总时间(包含和在你所在的牧场的奶牛的两次谈话时间)。 11 12 样例输入 13 5 7 14 10 15 10 16 20 17 6 18 30 19 1 2 5 20 2 3 5 21 2 4 12 22 3 4 17 23 2 5 15 24 3 5 6 25 26 样例输出 27 176 28 29 数据规模与约定 30 5 <= N <= 10000,N-1 <= P <= 1000000 <= Lj <= 10001 <= Ci <= 1,000

     分析:

    方案一:

    从顶点出发,找到顶点权值最小minx=min(minx,c[i])

    边已经按照权值大小从小向大排列,edge[1...m]

    每条边上权值  c[x]+c[y]+edge[i].w 

    father[1...n]对点的标记,将所有点的标记都变成一个值,就实现了所有点的遍历

    for(int j=1;j<=n;j++) if(father[j]==s2) father[j]=s1;  千万不能没有

    !!!熟记代码二

    //安慰奶牛 
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    #include <set>
    using namespace std;
    int n, p;
    int c[10010];
    int f[10010];
    struct node {
        int s, e, l;
    };
    node road[100100];
    int sum;
    bool cmp(node a, node b) {
        return a.l < b.l;
    }
    int find(int x) {
        if(f[x] == -1) return x;
        return f[x] = find(f[x]);
    }
    void merge(int x) {
        int t1 = find(road[x].s);
        int t2 = find(road[x].e);
        if(t1 != t2) {
            f[t1] = t2;
            sum += road[x].l;
        }
    }
    int main() {
        scanf("%d %d", &n, &p);
        memset(f, -1, sizeof(f));
        int i, j;
        int minc = 999999;
        for(i = 1; i <= n; i++) {
            scanf("%d", c + i);
            if(minc > c[i]) minc = c[i];
        }
        int s, e, l;
        for(i = 0; i < p; i++) {
            scanf("%d %d %d", &s, &e, &l);
            road[i].s = s, road[i].e = e, road[i].l = 2 * l + c[s] + c[e];
        }
        sort(road, road + p, cmp);
        sum = 0;
        for(i = 0; i < p; i++) {
            merge(i);
        }
        printf("%d
    ", sum + minc);
        return 0;
    }
    View Code

     注意并查集的解决方法,

    //最小生成树
    #include<iostream>
    #include<algorithm>
    using namespace std;
    struct node{
        int x,y,w;
    };
    const int inf=0x3f3f3f3f;
    const int maxn=100005;
    node edge[maxn];
    bool cmp(node a,node b){
        return a.w<b.w;
    }
    int n,m,father[maxn];
    int c[maxn];
    
    int main()
    {
        cin>>n>>m;//n个点m条边 
        int minx=inf;
        for(int i=1;i<=n;i++){
            cin>>c[i];
            minx=min(c[i],minx);//起始点 
            father[i]=i;
        }
        for(int i=1;i<=m;i++){
            cin>>edge[i].x>>edge[i].y>>edge[i].w;
            edge[i].w=2*edge[i].w+c[edge[i].x]+c[edge[i].y];
        } 
        sort(edge+1,edge+1+m,cmp);
        int ans=minx;
        for(int i=1;i<=m;i++){
            int s1=father[edge[i].x];
            int s2=father[edge[i].y];
            if(s1!=s2){
                ans+=edge[i].w;
                father[s2]=s1;//并查集 
                for(int j=1;j<=n;j++) if(father[j]==s2) father[j]=s1;
            }
        }
        cout<<ans<<endl;
    } 
    View Code
  • 相关阅读:
    (二)柯尼卡美能达bizhub_C368扫描打印机FTP设置内容及打印过程“华文宋体”打印出来乱码解决办法
    (一)柯尼卡美能达bizhub_C368扫描打印机驱动安装及扫描文件配置方法
    (二)谷歌浏览器版本 95.0.4638.54(正式版本) (64 位)表头标签有时候莫名其妙的出现一些不想要的标签解决办法
    (一)Windows7系统共享文件夹失灵,打开“网络发现”后自动关闭有效处理办法
    (三)ADO.NET学习心得
    (二)SQL 常见出现错误(附件、保存表、脱机、自增序列号 )
    (二)C#编程基础复习——变量和常量
    (一)C#编程基础复习——开启编程之旅
    selenium -webdriver
    org.springframework.orm.hibernate3.HibernateSystemException:
  • 原文地址:https://www.cnblogs.com/helloworld2019/p/10406935.html
Copyright © 2020-2023  润新知