zoukankan      html  css  js  c++  java
  • hdu_1875_畅通工程再续 prim和kruskal

    这个题是个典型的最小生成树的题目,但是刚开始怎么都过不了,后来发现两种写法都有疏忽,但是prim的到目前为止不懂为什么刚开始的不对,kruskal算法,并查集的初始条件从0开始写成从1开始了,所以已知wa,还有这个题比最小生成树一个卡点就是处理两点之间的距离的时候,要保证点都在10-1000之间。其它的没有什么坑了。

    代码一(prim)

    #include <stdio.h>
    #include <string.h>
    #include <math.h>
    #define INFI 999999999.0
    
    using namespace std;
    const int N = 130;
    typedef struct point
    {
        int x, y;
    }point;
    double Map[N][N];
    point p[N];
    int vis[N];
    double ans;
    double low_cost[N];
    double calc(int a, int b)
    {
        return sqrt((p[b].y - p[a].y) * (p[b].y - p[a].y) + (p[b].x - p[a].x) * (p[b].x - p[a].x));
    }
    void calc_distance(int n)
    {
        memset(Map, 0, sizeof(Map));
        double t;
        for (int i = 0; i < n; i++)
        {
            for (int j = i + 1; j < n; j++)    
            {
                t = calc(i, j);
                if (t >= 10 && t <= 1000)
                    Map[i][j] = Map[j][i] =calc(i, j);
                else
                    Map[i][j] = Map[j][i] = INFI;
            }
                
        }
    }
    int prim(int n)
    {
        for (int i = 0; i < n; i++)
            low_cost[i] = Map[0][i];
        vis[0] = 1;
        for (int i = 1; i < n; i++)
        {
            int k = 0;
            double min = INFI;
            for (int j = 1; j < n; j++)
            {
                if (!vis[j] && min > low_cost[j])
                {
                    min = low_cost[j];
                    k = j;
                }
            }
            if (k != 0)
            {
                vis[k] = 1;
                ans += min;
            }
            else
                return 0;
            for (int j = 1; j < n; j++)
            {
                if (!vis[j] && Map[k][j] < low_cost[j])
                    low_cost[j] = Map[k][j];
            }
        }
        return 1;
    }
    int main()
    {
        int T, C;
        scanf("%d", &T);
        while (T--)
        {
            memset(vis, 0, sizeof(vis));
            ans = 0.0;
            scanf("%d", &C);
            for (int i = 0; i < C; ++i)
                scanf("%d %d", &p[i].x, &p[i].y);
            calc_distance(C);
            int t = prim(C);
            if (t == 0)
            {
                puts("oh!");
                continue;
            }
            ans *= 100.0;
            printf("%.1f
    ", ans);
        }
        return 0;
    }
    View Code

    代码二(kruskal)

    #include<iostream>
    #include <stdio.h>
    #include <string.h>
    #include <math.h>
    #include <algorithm>
    #define EPS 1e-10
    using namespace std;
    struct Point{
        int x, y;
    };
    struct edge{
        int s, e;
        double dis;
    };
    const int N = 123;
    int father[N], num[N];
    Point p[N];
    edge E[N * N / 2];
    double ans = 0.0;
    void init(int n)
    {
        for (int i = 0; i <= n; ++i)
        { 
            father[i] = i;
            num[i] = 1;
        }
    }
    double calct(int a, int b)
    {
        return sqrt((p[b].y - p[a].y) * (p[b].y - p[a].y) + (p[b].x - p[a].x) * (p[b].x - p[a].x));
    }
    int calc_distance(int n)
    {
        int k = 0;
        for (int i = 0; i < n; i++)
        {
            for (int j = i + 1; j < n; j++)
            {
                double t = calct(i, j);
                if (t >= 10.0 && t <= 1000.0)
                {
                    E[k].s = i;
                    E[k].e = j;
                    E[k++].dis = t;
                }
            }
        }
        return k;
    }
    bool cmp(edge a, edge b)
    {
        return a.dis < b.dis;
    }
    int find(int x)
    {
        while (x != father[x])
            x = father[x];
        return father[x];
    }
    bool merge(int a, int b)
    {
        int ta = find(a);
        int tb = find(b);
        if (ta == tb)
            return false;
        if (num[ta] > num[tb])
        {
            father[tb] = ta;
            num[ta] += num[tb];
        }
        else
        {
            father[ta] = tb;
            num[tb] += num[ta];
        }
        return true;
    }
    bool kruskal(int n, int len)
    {
        int k = 0;
        for (int i = 0; i < len; i++)
        {
            if (merge(E[i].s, E[i].e))
            {
                ++k;
                ans += E[i].dis;
            }
            if (k == n - 1)
                break;
        }
        if (k == n - 1)
            return true;
        return false;
    }
    int main()
    {
        int t,n;
        scanf("%d", &t);
        while (t--)
        {
            scanf("%d", &n);
            init(n);
            ans = 0.0;
            for (int i = 0; i < n; i++)
                scanf("%d %d", &p[i].x, &p[i].y);
            int len = calc_distance(n);
            sort(E, E + len, cmp);
            if (kruskal(n, len))
            {
                printf("%.1f
    ", ans * 100.0);
            }
            else
                puts("oh!");
        }
        return 0;
    }
    View Code
  • 相关阅读:
    利用java反射机制,使用android系统的内部类成员函数
    Android2.2 API 中文文档系列(5) —— View
    android 的系统编译
    git reset使用
    linux解压 tar命令
    Android之Service与IntentService的比较
    .equ .long表示什么意思?
    解决Android平台布局xml文件的error parsing xml unbound prefix错误
    玩转C链表
    android下创建文件夹和修改其权限的方法
  • 原文地址:https://www.cnblogs.com/Howe-Young/p/4370151.html
Copyright © 2011-2022 走看看