hdu 1875(最小生成树kruskal)

/*

  Name: 最小生成树(kruskal) 

  Author: Try_86

  Date: 10/04/12 18:51

  Description: 不符合题意所述的距离不加进边集中,然后套用kruskal就可以了 

*/

#include <cmath>

#include <cstdio>

#include <cstdlib>

#include <iostream>



using namespace std;



const int M = 5050;



int p[M], sum;

struct edge {

    int a;

    int b;

    double dis;

}e[M];

struct point {

    double x;

    double y;

}po[101];



int cmp(const void *a, const void *b){

    if ((*(edge *)a).dis > (*(edge *)b).dis) return 1;

    return -1;

}



void init(int vs) {

    for (int i=1; i<=vs; ++i) p[i] = i;

    return ;

}



int find(int v) {

    if (p[v] != v) p[v] = find(p[v]);

    return p[v];

}



double join(edge e) {

    int x, y;

    x = find(e.a);

    y = find(e.b);

    if (x != y) {

        ++sum;

        p[x] = y;

        return e.dis;

    }

    return 0;

}



double kruskal(int es, int vs) {

    double ans = 0;

    init(vs);

    qsort(e, es, sizeof(edge), cmp);

    for (int i=0; i<es; ++i) {

        ans += join(e[i]);

        if (sum == vs) return ans;

    } 

    if (sum < vs) return -1;

}



int main() {

    int t;

    scanf ("%d", &t);

    while (t--) {

        int n, es;

        scanf ("%d", &n);

        for (int i=1; i<=n; ++i) scanf ("%lf%lf", &po[i].x, &po[i].y);

        if (n <= 1) {

            printf ("0.0\n");

            continue;

        }

        double dis;

        es = 0;

        for (int i=1; i<n; ++i) {

            for (int j=i+1; j<=n; ++j) {

                dis = sqrt((po[i].x-po[j].x)*(po[i].x-po[j].x)+(po[i].y-po[j].y)*(po[i].y-po[j].y));

                if (dis >= 10.0 && dis <= 1000.0) {

                    e[es].dis = dis;

                    e[es].a = i;

                    e[es].b = j;

                    ++es;

                }

            }

        }

        sum = 1;

        double ans = kruskal(es, n);

        if (ans < 0) printf ("oh!\n");

        else printf ("%.1lf\n", ans*100); 

    }

    return 0;

}

 

你可能感兴趣的:(最小生成树)