• 最小差异值 图论+贪心


    【问题描述】
    P 省刚经历一场不小的地震,所有城市之间的道路都损坏掉了,所以省长想
    请你将城市之间的道路重修一遍。
    因为很多城市之间的地基都被地震破坏导致不能修公路了,所以省长给定了
    你一些城市对,在这些城市对之间可以修公路,并且都有相应的价格。而且因为
    施工队伍有限,所以省长要求用尽量少的道路将所有的城市连通起来,这样施工
    量就可以尽量少,道路可视为无向边,且数据保证至少有一种连通的方案。不过,
    省长为了表示自己的公正无私,要求在满足上述条件的情况下,选择一种方案,
    使得该方案中最贵道路的价格和最便宜道路的价格的差值尽量小,即使这样的方
    案会使总价提升很多也没关系。
    那么,请你尽快地安排一种合理的方案,满足省长的要求。
    【输入格式】
    第一行两个数 N,M,表示城市的个数以及可以修的公路数;
    第二行开始 M 行,每行三个数 a,b,c,表示 a,b 之间可以修一条价值 c 的无向
    道路。
    【输出格式】
    一个数表示该方案中最大边减去最小边的值,要求要尽量的小。
    【样例输入】
    5 10
    1 2 9384
    1 3 887
    1 4 2778
    1 5 6916
    2 3 7794
    2 4 8336
    2 5 5387
    3 4 493
    3 5 6650
    4 5 1422

    【样例输出】
    1686
    【样例说明】
    选第 4,5,6,9 条边即可。
    【数据说明】
    30%数据满足 N<=M<=20
    100%数据满足 N<=M<=5000,0<c<=50000;


    相信大家看到这题,最先想到的肯定是最小生成树。但是最小生成树是求总路径最小的,而这题明确说了不考虑总长度,所以我们需要考虑怎么转换我们平时学的最小生成树。

    首先,要求差值最小,那一定就和大小有关,那我们先把边拿出来排一遍序。

    然后我们枚举最小边,不断往大加边,每加一条边就判断是否满足最小生成树,满足就和最小差值比较,然后枚举下一条小边(很明显)。

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    #define il inline
    #define db double
    using namespace std;
    il int gi()
    {
        int x=0,y=1;
        char ch=getchar();
        while(ch<'0'||ch>'9')
        {
            if(ch=='-')
            y=-1;
            ch=getchar();
        }
        while(ch>='0'&&ch<='9')
        {
            x=x*10+ch-'0';
            ch=getchar();
        }
        return x*y;
    }
    il ll gl()
    {
        ll x=0,y=1;
        char ch=getchar();
        while(ch<'0'||ch>'9')
        {
            if(ch=='-')
            y=-1;
            ch=getchar();
        }
        while(ch>='0'&&ch<='9')
        {
            x=x*10+ch-'0';
            ch=getchar();
        }
        return x*y;
    }
    struct edge
    {
        int a,b;
        ll dis;
    }e[5045];
    bool cmp(edge x,edge y)
    {
        return x.dis<y.dis;
    }
    int fa[5045];
    int find(int x)
    {
        if(fa[x]!=x)
        fa[x]=find(fa[x]);
        return fa[x];
    }
    int n,m,x,y,z,now;
    il bool hzr(int x,int y)
    {
        for(int i=1;i<=n;i++)
        fa[i]=i;
        for(int i=x;i<=y;i++)
        {
            int r1=find(e[i].a),r2=find(e[i].b);
            if(r1!=r2)
            {
                now++;
                fa[r2]=r1;
            }
        }
    }
    int main()
    {
        freopen("dvalue.in","r",stdin);
        freopen("dvalue.out","w",stdout);
        n=gi(),m=gi();
        for(int i=1;i<=m;i++)
        {
            x=gi(),y=gi(),z=gl();
            e[i].a=x;
            e[i].b=y;
            e[i].dis=z;
        }
        sort(e+1,e+1+m,cmp);
        ll minx=1e16;
        for(int i=1;i<=m-n+2;i++)
        {
            now=0;
            hzr(i,i+n-2);
            if(now==n-1)
            {
                if(e[i+n-2].dis-e[i].dis<minx)
                minx=e[i+n-2].dis-e[i].dis;
                continue;
            }
            for(int j=i+n-1;j<=m;j++)
            {
                int r1=find(e[j].a),r2=find(e[j].b);
                if(r1!=r2)
                {
                    now++;
                    fa[r2]=r1;
                }
                if(now==n-1)
                {
                    if(e[j].dis-e[i].dis<minx)
                        minx=e[j].dis-e[i].dis;
                    break;
                }
            }
        }
        printf("%lld
    ",minx);
        return 0;
    }
    PEACE
  • 相关阅读:
    NOI 模拟赛
    bzoj 4998 星球联盟
    bzoj 4545 DQS 的 Trie
    loj #161 子集卷积
    bzoj 5093 图的价值
    bzoj 4299 Codechef FRBSUM
    NOI 模拟赛
    WC2018 州区划分
    CSP 2020 T2 动物园
    CSP 2020 T1 儒略日
  • 原文地址:https://www.cnblogs.com/gshdyjz/p/7422913.html
Copyright © 2020-2023  润新知