HDU 1875

http://acm.hdu.edu.cn/showproblem.php?pid=1875

本人并查集专题:http://blog.csdn.net/fsafs168/article/details/7801010

/*
 * 并查集:这个题说明我掌握的还是不扎实
 * 同样的也在说明同一个专题十来道题至少需要
 * 本题思路是并查集+贪心
 * 首先遍历出所有城市的路径,构造并查集的边集
 * 然后根据距离,近的有限,依次并集。(贪心)
 * AC了、、、、、
 */


#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;

struct Node
{
    int x;
    int y;
}node[200];

struct Map
{
    int a;
    int b;
    double d;   //距离
}map[40000];

int father[200];

bool cmp(Map a, Map b)
{
    return a.d < b.d;
}

void ini(int n)
{
    for(int i=0;i<=n;i++)
    {
        father[i] = i;
    }
}

int find(int x)
{
    if(x != father[x])
        return find(father[x]);
    return father[x];
}
void sert(int a, int b)
{
    father[a]= b;
}
void printTest(int m, int n)
{
    for(int i=0;i<m;i++)
    {
        printf("test:%d %d %d %lf\n",i,map[i].a,map[i].b,map[i].d);
    }
    for(int i=0;i<=n;i++)
    {
        printf("test:f[%d] :%d\n",i,father[i]);
    }
}
double solve(int m)
{
    int i,j;
    double cost = 0;
    for(i=0;i<m;i++)
    {
        int a = find(map[i].a);
        int b = find(map[i].b);
        if(a!=b)
        {
            //printf("aaaaaaaaaaaaa\n");
            sert(a,b);
            cost += map[i].d;
        }
    }
    cost *= 100;
    return cost;
}

int main()
{
    int t,n;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        int i,j;
        double cost;
        int flag = -1;
        int m = 0;
        for(i=0;i<n;i++)
        {
            scanf("%d%d",&node[i].x,&node[i].y);
        }
        for(i=0;i<n-1;i++)
        {
            for(j=i+1;j<n;j++,m++)
            {
                map[m].a = i;
                map[m].b = j;
                map[m].d = sqrt((node[i].x-node[j].x)*(node[i].x-node[j].x)
                    +(node[i].y-node[j].y)*(node[i].y-node[j].y)*1.0);  //距离公式。注意是Double
                if(map[m].d<10||map[m].d>1000)  //题意中需要舍弃的距离
                {
                    m--;
                    continue;
                }
            }
        }
        ini(n);
        sort(map,map+m,cmp);
        //printTest(m,n);
        cost = solve(m);
        for(i=0;i<n;i++)
        {
            if(i == father[i])
                flag++;
        }
        //printf("test:  cost :%.1lf\n",cost);
        //printf("flag:%d\n",flag);
        if(!flag)
            printf("%.1lf\n",cost);
        else
            printf("oh!\n");
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值