zoukankan      html  css  js  c++  java
  • POJ2349二分+并查集,类似最小树的贪心

    题意:
          给你n个点,你的任务是构建一颗通讯树,然后给你一个s表示可以选出来s个点两两通讯不花钱,就是费用是0,其他的费用就是两点的距离,有个要求就是其他的费用中最大的那个最小。


    思路:
         方法比较多,题目也不难,但是容易有一个误区就是很多人认为这个题目是在求最小生成树,我不是这么想的(虽然这个题目可以用最小树的算法过,但是我的感觉是他和最小树是相同的代码,不同的思想),因为最小树毕竟是求全局和的最小,而这个题目是求全局中最大的最小,这样首先容易让人想到的就是直接二分,二分距离,然后去用并查集或者是搜索啥的去判断联通快个数啥的,这样是很容易理解的,我试了下,可以ac,但是回来说最小树,这个题目直接用最小树的算法也可以ac,但是思路和最小树的想法没啥关系,在克鲁斯卡尔里,大体思想是 排序后 如果当前这两个连通块没有连接,那么就直接用最小的代价,也就是当前的花费去连接,因为早晚都得连接,不如趁现在最省的时候,就这样贪心到最后就是最下生成树,但是这个题目的想法却是,既然你是求最大的最小,那么我们排序后就一个一个往里面添加,知道满足要求的时候就直接停止就行了。和最小树的写法没啥区别,但是理论依据不同,这个要清楚。还有就是我用两种方法写了下(还可以有更多方法,什么二分+搜索啥的都行),其中一个是类似最小树那样,另一个是二分+并查集,我的二分里面没啥大优化,如果像更快的话,二分的时候可以直接二分任意两点所有的距离,就是说答案肯定是任意两点距离中的一个,这样可以缩短二分范围。。。。。




    二分+并查集
    #include<math.h>
    #include<stdio.h>
    #include<algorithm>


    #define eps 0.000001


    using namespace std;


    typedef struct
    {
        int x ,y;
    }NODE;


    typedef struct
    {
        int a ,b;
        double c;
    }EDGE;


    NODE node[500+5];
    EDGE edge[500*500/2+10];
    int mer[500+5] ,n ,m;


    bool camp(EDGE a ,EDGE b)
    {
        return a.c < b.c;
    }


    int finds(int x)
    {
        return x == mer[x] ? x : mer[x] = finds(mer[x]);
    }


    bool ok(int nowid ,double now)
    {
        for(int i = 1 ;i <= n ;i ++)
        mer[i] = i;
        int s = 0;
        for(int i = 1 ;i <= nowid ;i ++)
        {
            if(edge[i].c > now) break;
            int x = finds(edge[i].a);
            int y = finds(edge[i].b);
            if(x == y) continue;
            s ++;
            mer[x] = y;
            if(s + m >= n) return 1;
        }
        return 0;


    }


    double Search2(int nowid)
    {
        double low = 0 ,up = edge[nowid].c;
        double mid;
        while(up - low >= eps)
        {
            mid = (low + up) / 2;
            if(ok(nowid ,mid))
            up = mid - eps;
            else low = mid + eps;
        }
        return low;
    }


    double GetDis(NODE a ,NODE b)
    {
        double x = (a.x - b.x) * (a.x - b.x);
        double y = (a.y - b.y) * (a.y - b.y);
        return sqrt(x + y);
    }


    int main ()
    {
        int t ,i ,j ,nowid;
        scanf("%d" ,&t);
        while(t--)
        {
            scanf("%d %d" ,&m ,&n);
            nowid = 0;
            for(i = 1 ;i <= n ;i ++)
            {
                scanf("%d %d" ,&node[i].x ,&node[i].y);
                for(j = 1 ;j < i ;j ++)
                {
                    ++nowid;
                    edge[nowid].a = i;
                    edge[nowid].b = j;
                    edge[nowid].c = GetDis(node[i] ,node[j]);
                }
            }
            if(m >= n)
            {
                printf("0.00 ");
                continue;
            }
            sort(edge + 1 ,edge + nowid + 1 ,camp);
            printf("%.2lf " ,Search2(nowid));
        }
        return 0;
    }






    贪心+并查集


    #include<math.h>
    #include<stdio.h>
    #include<algorithm>


    using namespace std;


    typedef struct
    {
        int a ,b;
        double c;
    }EDGE;


    typedef struct
    {
        int  x ,y;
    }NODE;


    NODE node[500+5];
    EDGE edge[500*500/2+10];
    int mer[500+5];


    bool camp(EDGE a ,EDGE b)
    {
        return a.c < b.c;
    }


    int finds(int x)
    {
        return x == mer[x] ? x : mer[x] = finds(mer[x]);
    }


    double GetDis(NODE a, NODE b)
    {
        double x = (a.x - b.x) * (a.x - b.x);
        double y = (a.y - b.y) * (a.y - b.y);
        return sqrt(x + y);
    }




    int main ()
    {
        int t ,n ,m ,i ,j;
        scanf("%d" ,&t);
        while(t--)
        {
            scanf("%d %d" ,&m ,&n);
            int nowid = 0;
            for(i = 1 ;i <= n ;i ++)
            {
                mer[i] = i;
                scanf("%d %d" ,&node[i].x ,&node[i].y);
                for(j = 1 ;j < i ;j ++)
                {
                    ++nowid;
                    edge[nowid].c = GetDis(node[i] ,node[j]);
                    edge[nowid].a = i ,edge[nowid].b = j;
                }
            }
            if(m >= n)
            {
                printf("0 ");
                continue;
            }
            sort(edge + 1 ,edge + nowid + 1 ,camp);
            int edges = 0;
            for(i = 1 ;i <= nowid ;i ++)
            {
                int x = finds(edge[i].a);
                int y = finds(edge[i].b);
                if(x == y)continue;
                edges ++;
                mer[x] = y;
                if(edges + m >= n)
                {
                    printf("%.2lf " ,edge[i].c);
                    break;
                }
            }


        }
        return 0;
    }









  • 相关阅读:
    iOS resign code with App Store profile and post to AppStore
    HTTPS科普扫盲帖 对称加密 非对称加密
    appid 评价
    使用Carthage安装第三方Swift库
    AngularJS:何时应该使用Directive、Controller、Service?
    xcode7 The operation couldn't be completed.
    cocoapods pod install 安装报错 is not used in any concrete target
    xcode7 NSAppTransportSecurity
    learning uboot how to set ddr parameter in qca4531 cpu
    learning uboot enable protect console
  • 原文地址:https://www.cnblogs.com/csnd/p/12062503.html
Copyright © 2011-2022 走看看