• Aizu2224-Save your cats


    链接:https://vjudge.net/problem/Aizu-2224

    题意:n为魔法桩的数量,m为围栏的数量,第2到n+1行为每个魔法桩的坐标,第n+2到m+1行表示两个桩之间有围栏,每个封闭的区域内都有至少一只猫,需要的圣水数量与围栏长度成正比,问救出所有猫需要破坏的围栏长度。

    分析:由题意可知要去掉一些边,使得该图变成树,求这些边的最小和。我们倒过来求该图的最大生成树,事先求出所有边的权和,然后相减即可。

    代码(Kruskal算法):

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cmath>
     4 #include <algorithm>
     5 using namespace std;
     6 int n,m,f[11000],cnt;
     7 double ans,k;
     8 struct node
     9 {
    10     int x,y;
    11 }p[11000];
    12 struct edge
    13 {
    14     int u,v;
    15     double dis;
    16 }e[110000];
    17 bool cmp(edge a,edge b)
    18 {
    19     return a.dis>b.dis;
    20 }
    21 int find(int k)
    22 {
    23     if(f[k]==k)return k;
    24     return f[k]=find(f[k]);
    25 }
    26 double powAnd(int i,int j)
    27 {
    28     return 1.0*((p[i].x-p[j].x)*(p[i].x-p[j].x)+(p[i].y-p[j].y)*(p[i].y-p[j].y));
    29 }
    30 int main(void)
    31 {
    32     scanf("%d %d",&n,&m);
    33     for(int i=1;i<=n;i++)
    34     {
    35         f[i]=i;
    36         scanf("%d %d",&p[i].x,&p[i].y);
    37     }
    38     for(int i=1;i<=m;i++)
    39     {
    40         scanf("%d %d",&e[i].u,&e[i].v);
    41         e[i].dis=sqrt(powAnd(e[i].u,e[i].v));
    42         ans+=e[i].dis;
    43     }
    44     sort(e+1,e+1+m,cmp);
    45     for(int i=1;i<=m;i++)
    46     {
    47         int fu=find(e[i].u),fv=find(e[i].v);
    48         if(fu==fv)continue;
    49         f[fu]=fv;
    50         k+=e[i].dis;
    51         if(++cnt==n-1)break;
    52     }
    53     printf("%f",ans-k);
    54     return 0;
    55 }
  • 相关阅读:
    什么是OOAD?什么是UML?
    Linux下Gvim 的基本操作-适合新手看
    关于mongodb ,redis,memcache之间见不乱理还乱的关系和作用
    phpcms常用标签
    请问如何更改dedecms“文件保存目录”的字符限制 ?
    如何通过刷百度指数来提高网站的权重
    HDU 1263(水果统计 **)
    HDU 1284(钱币兑换 背包/母函数)
    HDU 1028(数字拆分 分治)
    HDU 1036(平均速度 **)
  • 原文地址:https://www.cnblogs.com/yanying7/p/13415391.html
Copyright © 2020-2023  润新知