• Aizu 2224(并查集)


    http://acm.hust.edu.cn/vjudge/contest/125004#problem/B

    题意:一个邪恶的女巫因为嫉妒Nicholas家的猫可爱,就施了魔法让他家的猫咪困在卷子里出不来了(要不然说她邪恶呢)。现在给出她施魔法变出来的桩的坐标,栅栏i与栅栏j(是一个整体,也就是给出了一条边,边的长度是第i个桩与第j个桩间的长度)。现在让你求最少需要破坏多长的栅栏才能让可爱的猫咪都出来。

    分析:若想要让猫咪出来的话,肯定是不能有环了。那么现在就有一个思想:算出全部边长总和,然后减去可以构成的最大生成树的总和(不能有环,生成树正好符合这样的条件),那么剩下的就是需要被破坏的边的总和。但是怎样求最大生成树呢?我们需要用到并查集,首先将边存在结构体里,然后按照从大到小将边长排序,接着需要遍历m条边,当加入某条边时,若两端的father[x]不同,则需要进行归并(father[x]=y),若相同的话,自然不需要加它这条边的边长了(相同的话,会构成一个封闭区间)。

    注意:没有说m的范围,在开有关m的数组时,需要比n大。

     

    #include<stdio.h>
    #include<string.h>
    #include<iostream>
    #include<algorithm>
    #include<math.h>
    #define maxn 11000
    #define oo 0xfffffff
    using namespace std;
    int father[maxn], n, m;
    
    struct node
    {
        int u, v;
        double w;
    
    } s[maxn*100];///数组大小
    
    struct point
    {
        int x, y;
    } a[maxn];
    
    double Len(int p, int q)
    {
        double d = sqrt((a[p].x-a[q].x)*(a[p].x-a[q].x)+(a[p].y-a[q].y)*(a[p].y-a[q].y));
        return d;
    }
    
    int Find(int x)
    {
       while(x!=father[x])
       {
            x=father[x];
       }
        
         return x;
    }
    
    int cmp(node p, node q)
    {
        return p.w>q.w;
    }
    
    double solve()
    {
        double ans = 0;
    
        for(int i=0; i<m; i++)
        {
            int ru = Find(s[i].u);
            int rv = Find(s[i].v);
    
            if(ru != rv)
            {
                father[ru] = rv;
                ans += s[i].w;
            }
    
        }
    
        return ans;
    }
    
    
    int main()
    {
        int u, v;
    
        while(scanf("%d %d",&n, &m)!=EOF)
        {
            double sum = 0;
    
            for(int i=1; i<=n; i++)
                scanf("%d %d", &a[i].x, &a[i].y);
    
            for(int i=1; i<=n; i++)
                father[i] = i;
    
            for(int i=0; i<m; i++)
            {
                scanf("%d %d", &u, &v);
                s[i].u = u;
                s[i].v = v;
                s[i].w = Len(u, v);
    
                sum += s[i].w;
            }
    
            sort(s, s+m, cmp);
    
            double l = solve();
    
            printf("%.3f
    ", sum-l);
        }
    
        return 0;
    }
    View Code
  • 相关阅读:
    iOS 关于第三方键盘
    linux分期挂载永久生效
    linux echo 用法 【 -e c 体会】
    expr index
    tail -f 不好用? 用法小解析
    【Linux】su
    Linux 下mv命令使用 目标目录不存在时会更名被目标目录并放在/目录下
    Java一点笔试题【2016-04-13】
    Linux 上重启tomcat 【转】 http://www.cnblogs.com/tovep/articles/2473147.html
    Oracle Merge into [转] [ http://www.cnblogs.com/dongsheng/p/4384754.html]
  • 原文地址:https://www.cnblogs.com/daydayupacm/p/5724950.html
Copyright © 2020-2023  润新知