hdu 1875 畅通工程再续

最小生成树 ——kruscal算法和prim算法

kruscal算法
代码:

#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
struct Island
{
    int x, y;
} arr[500];
struct node
{
    int u, v;
    double w;
} edge[2000];
int per[220];
int n;
bool cmp(node a,node b)
{
    return a.w < b.w;
}
void init()
{
    for(int i=1; i<=n; ++i)
    {
        per[i]=i;
    }
}
int find(int x)
{
    if(x==per[x]) return x;
    return per[x]=find(per[x]);
}
bool join(int x,int y)
{
    int fx=find(x);
    int fy=find(y);
    if(fx!=fy)
    {
        per[fx]=fy;
        return 1;
    }
    return 0;
}
int main()
{
    int T;
    int i, j, k;
    double x, y;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%d", &n);
        init();
        for(i = 1; i <= n; i++)
        {
            scanf("%d%d", &arr[i].x, &arr[i].y);
        }
        k=0;
        for(i = 1; i <= n; i++) //把所有路记录在node结构体中
        {
            for(j = i+1; j <= n; j++)
            {
                edge[k].u = i;
                edge[k].v = j;
                x = (arr[j].y-arr[i].y) * (arr[j].y-arr[i].y);
                y = (arr[j].x-arr[i].x) * (arr[j].x-arr[i].x);
                double temp = sqrt(x+y);
                edge[k++].w = temp;
            }
        }
        sort(edge, edge+k, cmp);
        double sum = 0;
        for(i = 0; i < k; i++)
        {
            if(edge[i].w <= 1000 && edge[i].w >= 10 && join(edge[i].u,edge[i].v))//如果两个岛的距离不符合要求就会把join(edge[i].u,edge[i].v)短路
            {
                sum += edge[i].w;
            }
        }
        int cnt = 0;
        bool flag = 0;
        for(i = 1; i <= n; i++) //短路了就不会执行了,也就不会连接了,就只需要判断根节点的个数
        {
            if(i == per[i]) cnt++;
            if(cnt > 1) //不等于1就还有元素(小岛)没连起来,不满足题意
            {
                flag = 1;
                break;
            }
        }
        if(flag) printf("oh!\n");
        else
            printf("%.1lf\n", sum*100);
    }
    return 0;
}


prim算法
代码:

#include <cstdio>
#include <cmath>
#define INF 0x3f3f3f3f
using namespace std;

struct nod
{
    double x, y, w;
}node[105];
double map[105][105], sum;
int s[105], n;

void set()
{
    double d;
    for(int i = 1; i <= n; i++)
    {
        s[i]=0; node[i].w = INF;
        for(int j = i + 1; j <= n; j++)
        {
            d = sqrt(pow(node[i].x-node[j].x, 2) + pow(node[i].y-node[j].y, 2));
            if(d >= 10 && d <= 1000)
            map[i][j] = map[j][i] = d*100;
            else
             map[i][j] = map[j][i] = INF;
        }
    }
}
int Prim(int m)
{
    double min;
    int t = 1;
    s[m] = 1; sum=0;
    for(int k = 2; k <= n; k++)
    {
        for(int i = 1; i <= n; i++)
        if(s[i] == 0 && node[i].w > map[m][i])
        node[i].w = map[m][i];

        min = INF;
        for(int j = 1; j <= n; j++)
        if(s[j] == 0 && min > node[j].w)
        {
            min = node[j].w;
            m = j;
        }
        if(s[m] == 0)
        {
            t++;
            sum += min;
            s[m] = 1;
        }
    }
    if(t == n) return 1;
    return 0;
}

int main()
{
    int t, k;
    scanf("%d", &k);
    while(k--)
    {
        scanf("%d", &n);
        for(int i = 1; i <= n; i++)
        scanf("%lf%lf", &node[i].x, &node[i].y);

        set();
        t = Prim(1);
        if(t != 0)
            printf("%.1lf\n", sum);
        else
            printf("oh!\n");
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值