zoukankan      html  css  js  c++  java
  • Aizu:2224-Save your cats

    Save your cats

    Time limit 8000 ms
    Memory limit 131072 kB

    Problem Description

    Nicholas Y. Alford was a cat lover. He had a garden in a village and kept many cats in his garden. The cats were so cute that people in the village also loved them.

    One day, an evil witch visited the village. She envied the cats for being loved by everyone. She drove magical piles in his garden and enclosed the cats with magical fences running between the piles. She said “Your cats are shut away in the fences until they become ugly old cats.” like a curse and went away.

    Nicholas tried to break the fences with a hummer, but the fences are impregnable against his effort. He went to a church and asked a priest help. The priest looked for how to destroy the magical fences in books and found they could be destroyed by holy water. The Required amount of the holy water to destroy a fence was proportional to the length of the fence. The holy water was, however, fairly expensive. So he decided to buy exactly the minimum amount of the holy water required to save all his cats. How much holy water would be required?

    Input

    The input has the following format:

    N M
    x1 y1
    .
    .
    .
    xN yN
    p1 q1
    .
    .
    .
    pM qM

    The first line of the input contains two integers N (2 ≤ N ≤ 10000) and M (1 ≤ M). N indicates the number of magical piles and M indicates the number of magical fences. The following N lines describe the coordinates of the piles. Each line contains two integers xi and yi (-10000 ≤ xi, yi ≤ 10000). The following M lines describe the both ends of the fences. Each line contains two integers pj and qj (1 ≤ pj, qj ≤ N). It indicates a fence runs between the pj-th pile and the qj-th pile.

    You can assume the following:

    No Piles have the same coordinates.
    A pile doesn’t lie on the middle of fence.
    No Fences cross each other.
    There is at least one cat in each enclosed area.
    It is impossible to destroy a fence partially.
    A unit of holy water is required to destroy a unit length of magical fence.
    

    Output

    Output a line containing the minimum amount of the holy water required to save all his cats. Your program may output an arbitrary number of digits after the decimal point. However, the absolute error should be 0.001 or less.
    Sample Input 1

    3 3
    0 0
    3 0
    0 4
    1 2
    2 3
    3 1

    Example

    Output for the Sample Input 1

    3.000

    Sample Input 2

    4 3
    0 0
    -100 0
    100 0
    0 100
    1 2
    1 3
    1 4

    Output for the Sample Input 2

    0.000

    Sample Input 3

    6 7
    2 0
    6 0
    8 2
    6 3
    0 5
    1 7
    1 2
    2 3
    3 4
    4 1
    5 1
    5 4
    5 6

    Output for the Sample Input 3

    7.236

    Sample Input 4

    6 6
    0 0
    0 1
    1 0
    30 0
    0 40
    30 40
    1 2
    2 3
    3 1
    4 5
    5 6
    6 4

    Output for the Sample Input 4

    31.000


    解题心得:

    1. 很有意思的一个题,说是一个人养了很多的猫,巫师看不惯,用很多桩子和墙将这些猫全部围困了起来(每个墙的起点和终点都在桩子上,每堵墙不交叉,每个围起来的格子里面都有猫),每个桩子有一个坐标,你需要用圣水去将墙消融,将猫放出来,每单位长度墙要用一单位圣水,问最少需要多少圣水。
    2. 首先要明白要将所有的猫都放出来就不能有格子,怎么看有没有格子(也就是环),使用并查集,然后要转换一个思想,那就是不能想怎么去拆除墙,因为拆除墙是没有办法倒着来使用并查集的。可以先得到所有的墙的长度的总和,然后建立一个最”大“生成树,用所有墙长度的总和减去建立最大生成树使用的长度就是需要拆除的长度。

    #include <math.h>
    #include <stdio.h>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int maxn = 1e6+100;
    
    struct Pile{
        int x,y;
    }p[maxn];
    
    struct Fence{
        double len;
        int s,e;
    
        bool operator < (const Fence &a) const {
            return a.len < len;
        }
    }f[maxn];
    
    int n,m,father[maxn];
    double tot;
    
    double get_len(int x,int y){
        double x1 = p[x].x;
        double y1 = p[x].y;
        double x2 = p[y].x;
        double y2 = p[y].y;
    
        double len = (x1-x2)*(x1-x2) + (y1-y2)*(y1-y2);
        len = sqrt(len);
    
        return len;
    }
    
    void init() {
        tot = 0;
        for(int i=1;i<=n;i++)
            father[i] = i;
        for(int i=1;i<=n;i++)
            scanf("%d%d",&p[i].x,&p[i].y);
        for(int i=0;i<m;i++) {
            scanf("%d%d", &f[i].s, &f[i].e);
            f[i].len = get_len(f[i].s,f[i].e);
            tot += f[i].len;
        }
        sort(f,f+m);
    }
    
    int find(int x) {
        if(x == father[x])
            return x;
        return father[x] = find(father[x]);
    }
    
    void merge(int x,int y){
        int fx = find(x);
        int fy = find(y);
        father[fx] = fy;
    }
    
    void build_tree() {
        double add = 0;
        for(int i=0;i<m;i++) {
            if(find(f[i].s) != find(f[i].e)) {
                add += f[i].len;
                merge(f[i].e,f[i].s);
            }
        }
        printf("%.3f
    ",tot-add);
    }
    
    int main() {
        while(scanf("%d%d",&n,&m) != EOF) {
            init();
            build_tree();
        }
        return 0;
    }
  • 相关阅读:
    select和epoll的区别
    Epoll导致的selector空轮询
    2.集合框架中的泛型有什么优点?
    java的语法基础(二)
    17-文本属性和字体属性
    15-浮动
    16-margin的用法
    14-块级元素和行内元素
    12-简单认识下margin
    day15 什么是递归/递归与回溯
  • 原文地址:https://www.cnblogs.com/GoldenFingers/p/9107143.html
Copyright © 2011-2022 走看看