HDOJ-1875-畅通工程再续 解题报告

来源:互联网 发布:网络音视频许可证 编辑:程序博客网 时间:2024/05/20 21:47

       一道最小生成树题目。题意为中文描述不多说。比起一般的最小生成树题目来说,本题需要考虑浮点数的比较,另外对边长也有限制(如题目所说:两岛之间的距离不能小于10米也不能大于1000米),也就是说在此情况下不能直接将两小岛连通。


       我的解题思路:首先计算和比较浮点数的大小要尤其注意,其次根据题意,两岛之间的距离不满足题目要求的视做无法直接连通。注意这两点之后用kruskal算法或者prim算法解决就可以了。


       下面是解题代码:kruskal解法

#include <stdio.h>#include <stdlib.h>#include <math.h>#define N 105typedef struct side     //定义边结构体{    int a, b;       //两点(岛)的下标    double len;     //边长(距离)}side;typedef struct point    //定义点结构体{    int x, y;   //坐标}point;point p[N];side s[N*N];int bleg[N];    //并查集使用,存储父节点int pn;     //点的数量int sn;     //边的数量int t;      //测试样例数void Init();        //初始化void Read();        //输入double Count(int i, int j);     //计算边长void Kruskal();int Mycmp(const void *a, const void *b);    //qsort比较函数int Find(int x);    //并查集查找void Union(int x, int y);   //并查集合并int Test();     //检测工程是否畅通int main(){    scanf("%d", &t);    while (t--)    {        Init();        Read();        Kruskal();    }    return 0;}void Init()         //初始化{    int i;    for (i=0; i<N; ++i)    {        bleg[i] = i;    }    sn = pn = 0;    return;}void Read()         //输入{    int i, j;    scanf("%d", &pn);    for (i=0; i<pn; ++i)    {        scanf("%d %d", &p[i].x, &p[i].y);        for (j=0; j<i; ++j)     //开始计算新增的边        {            s[sn].a = i;            s[sn].b = j;            s[sn++].len = Count(i, j);        }    }    return;}double Count(int i, int j)      //计算边长{    double dx = ((double)p[i].x - p[j].x) * (p[i].x - p[j].x);    double dy = ((double)p[i].y - p[j].y) * (p[i].y - p[j].y);    return sqrt(dx + dy);}void Kruskal(){    int i;    double ans = 0;    qsort(s, sn, sizeof(side), Mycmp);    for (i=0; i<sn; ++i)    //忽略边长小于10的边    {        if (s[i].len >= 10) break;    }    for (; i<sn; ++i)    {        if (s[i].len <= 1000 && Find(s[i].a) != Find(s[i].b))       //要求边长小于等于1000        {            ans += s[i].len;            Union(s[i].a, s[i].b);        }    }    if (Test() == 1)    {        printf("%.1f\n", 100 * ans);    }    else    {        printf("oh!\n");    }    return;}int Mycmp(const void *a, const void *b)     //qsort比较函数{    if ((*(side *)a).len > (*(side *)b).len)    {        return 1;    }    return -1;}int Find(int x)     //并查集查找{    int y = bleg[x];    int z;    while (y != bleg[y])    {        y = bleg[y];    }    while (x != bleg[x])    {        z = bleg[x];        bleg[x] = y;        x = z;    }    return y;}void Union(int x, int y)        //并查集合并{    int fx = Find(x);    int fy = Find(y);    bleg[fx] = fy;    return;}int Test()      //检测工程是否畅通{    int i;    int x = bleg[0];    for (i=1; i<pn; ++i)    {        if (bleg[i] != x)   //出现有两小岛不属于同一个集合时说明工程未畅通        {            return 0;        }    }    return 1;}


0 0
原创粉丝点击