HDU 1875 畅通工程再续(最小生成树-Kruskal)

来源:互联网 发布:淘宝3c证书是什么 编辑:程序博客网 时间:2024/06/11 09:08

Description

给N个坐标,在能建立的坐标之间距离小于1000并且大于10可以建立连接,连接的花费是坐标的距离,计算最小生成树,如果有一个坐标不能与其他任意一个坐标连接则输出oh。

Input

输入包括多组数据。输入首先包括一个整数T(T <= 200),代表有T组数据。
每组数据首先是一个整数C(C <= 100),代表小岛的个数,接下来是C组坐标,代表每个小岛的坐标,这些坐标都是 0 <= x, y <= 1000的整数。

Output

每组输入数据输出一行,代表建桥的最小花费,结果保留一位小数。如果无法实现工程以达到全部畅通,输出”oh!”.

Sample Input

2
2
10 10
20 20
3
1 1
2 2
1000 1000

Sample Output

1414.2
oh!

Solution

构建一个边的struct,用一个数组存储边,求出任意两点间距离,只要介于10~1000之间就建边,然后套MST模版即可 。

code

#include <iostream>#include <cmath>#include <algorithm>#include <cstdio>#include <cstring>using namespace std;struct Edge{    int u, v;    double w;};const int INF = 0x3f3f3f3f;Edge edges[11000];int x[110], y[110];int pre[150];int num;void init(){    for (int i = 1; i <= num; i++)        pre[i] = i;}int find(int x){    if (x == pre[x])        return x;    return pre[x] = find(pre[x]);}void unite(int i, int j){    if (find(i) != find(j))        pre[find(j)] = find(i);}bool cmp(Edge a, Edge b){    if (a.w != b.w)        return a.w < b.w;    if (a.u != b.u)        return a.u < b.u;    return a.v < b.v;}double kruskal(){    double ans = 0;    sort(edges + 1, edges + 1 + num * num, cmp);    for (int i = 1; i <= num * num; i++)    {        if (edges[i].w != INF && (find(edges[i].u) != find(edges[i].v)))        {            unite(edges[i].u, edges[i].v);            ans += edges[i].w;        }    }    for (int i = 2; i <= num; i++)        if (find(i) != find(1))            return -1;    return ans * 100;}int main(){    // freopen("in.txt", "r", stdin);    int T;    scanf("%d", &T);    while (T--)    {        scanf("%d", &num);        init();        for (int i = 1; i <= num; i++)            scanf("%d%d", &x[i], &y[i]);        int t_cnt = 1;        for (int i = 1; i <= num; i++)            for (int j = 1; j <= num; j++)            {                edges[t_cnt].u = i, edges[t_cnt].v = j;                double tx = x[i] - x[j], ty = y[i] - y[j];                double dis = sqrt(tx * tx + ty * ty);                if (dis > 1000 || dis < 10)                    edges[t_cnt].w = INF;                else                    edges[t_cnt].w = dis;                t_cnt++;            }        double ans = kruskal();        if (ans == -1)            printf("oh!\n");        else            printf("%.1f\n", ans);    }    return 0;}
阅读全文
0 0